Card deposits add external fiat funds to a PayCA account. The API is provider-independent: your integration uses PayCA credentials and PayCA deposit statuses, while PayCA selects the acquiring route.
Deposit access is enabled per client. Ask your PayCA account manager to enable the required currencies and allow-list your checkout return URLs before starting the integration.
Two Kinds of Card Option #
A card funding option works in one of two ways. The funding options response tells you which one applies (cardDetailsRequired):
cardDetailsRequired |
Who collects the card | What the payer sees |
|---|---|---|
absent or false |
A hosted checkout page. | You redirect the payer to checkoutUrl; the page collects the card and runs 3-D Secure. |
true |
You, in your own form. | You send the card with the create request. The payer is redirected only if the card issuer asks for 3-D Secure. |
For the complete flow with card details, including payouts, see EUR Card Top-ups and Payouts. Which kind your client gets is set by PayCA per client. The currencies your accounts can be topped up by card in are listed by GET /v1/client/settings (see Accounts in Several Currencies and Exchange).
Choosing the Card Acquirer per Request #
Every client has a default card acquirer, and PayCA can allow a client further acquirers it may select per request. This suits a platform that routes the deposits of its own merchants differently: one merchant through one acquirer, another through a second, a third through both or none. If you send nothing, nothing changes: every request is served by your default acquirer, as before.
GET /v1/client/settings returns your acquirers in cardAcquirers:
| Field | Meaning |
|---|---|
default |
The acquirer that serves a request which does not select acquirers. |
allowed |
Every acquirer you may select, the default first. |
currencies |
For each allowed acquirer, the currencies whose accounts it tops up by card for you; an empty list when it currently tops up none. |
The codes are opaque identifiers assigned by PayCA. Read them from cardAcquirers.allowed instead of hard-coding them. cardFundingCurrencies keeps listing the default acquirer's currencies only; an account may be opened in a currency of any allowed acquirer.
To select acquirers, send the same choice to every step of one deposit:
| Endpoint | How |
|---|---|
GET /v2/accounts/{accountId}/funding-options |
Query parameter acquirers, comma-separated, for example ?country=DE&acquirers=<code>,<code>. |
POST /v2/accounts/{accountId}/deposit-quote |
Body field acquirers, an array of codes. |
POST /v2/accounts/{accountId}/deposits |
Body field acquirers, an array of codes. |
- Absent: your default acquirer serves the request.
- A list: only the listed acquirers that are in
cardAcquirers.allowedmay serve it. A code that is unknown or not allowed for you is ignored, not refused. - Empty (
acquirers=or"acquirers": []): no acquirer is selected. Funding options return no card option, and a quote or create is refused with400, as for any card method that is not available.
Each acquirer serves its own currencies, so the account's currency decides which of the selected acquirers takes the deposit. If none of them serves that currency, the card method is not available for the request. Funding methods that do not go through a card acquirer are not affected by acquirers.
Card payouts take the same acquirers selection: see Selecting the acquirer for a payout.
Integration Flow #
- Request the funding options available for the account currency and payer country.
- Quote the amount the payer will be charged and the amount the account will receive.
- Create one deposit order with an
Idempotency-Keyand the quoted values — with the payer's card when the option hascardDetailsRequired: true. - Redirect the payer to the returned
checkoutUrlwhen there is one. - Retrieve the deposit until it reaches a terminal status.
- Subscribe to
depositwebhooks for status events and later reversals.
A checkout redirect is not proof that funds are available. Treat only status: completed as a successful account credit.
Prerequisites #
You need:
- PayCA
x-client-idandx-client-secretcredentials. - An active PayCA account in the currency you want to receive.
- Card deposits enabled for your client, account currency, and payer country.
- HTTPS complete and cancel redirect URL prefixes allow-listed by PayCA.
- A webhook endpoint registered with
type: deposit. - For options with
cardDetailsRequired: true: PCI DSS compliance for the systems that collect and transmit card data, the payer's full profile (see Step 3) and the IP address of the payer's device.
The deposit currency always equals the target account currency. Card deposit and currency conversion are separate operations; no FX conversion happens during a deposit.
Step 1 - Discover Funding Options #
Call GET /v2/accounts/{accountId}/funding-options with the payer's ISO 3166-1 alpha-2 billing country.
curl -s "$PAYCA_BASE_URL/v2/accounts/$ACCOUNT_ID/funding-options?country=US" \
-H "x-client-id: $PAYCA_CLIENT_ID" \
-H "x-client-secret: $PAYCA_CLIENT_SECRET"
Example response:
{
"options": [
{
"method": "card",
"currency": "USD",
"minAmount": "20.00",
"maxAmount": "999.00",
"fee": {
"mode": "add_on",
"rate": "5.00",
"fixed": "1.00",
"declineRate": "2.00",
"declineFixed": "0.50",
"refundRate": "3.00",
"refundFixed": "0.25",
"chargebackFixed": "15.00"
}
}
]
}
An option where you collect the card carries "cardDetailsRequired": true:
{
"options": [
{
"method": "card",
"currency": "EUR",
"minAmount": "10.00",
"maxAmount": "1000.00",
"cardDetailsRequired": true
}
]
}
The values above are illustrative. Always use the response returned for the current client, account currency, and country. An empty options array means no external funding method is currently available for that combination.
Step 2 - Quote the Deposit #
Use POST /v2/accounts/{accountId}/deposit-quote before showing a price or opening a checkout.
amountMode determines which amount the caller controls:
| Mode | Meaning |
|---|---|
credited |
amount is what the PayCA account should receive. |
charged |
amount is the maximum total the payer should be charged. |
curl -s -X POST "$PAYCA_BASE_URL/v2/accounts/$ACCOUNT_ID/deposit-quote" \
-H "Content-Type: application/json" \
-H "x-client-id: $PAYCA_CLIENT_ID" \
-H "x-client-secret: $PAYCA_CLIENT_SECRET" \
-d '{
"method": "card",
"amount": "20.00",
"amountMode": "credited",
"country": "US"
}'
Example response:
{
"requestedAmount": "20.00",
"amountMode": "credited",
"currency": "USD",
"processingFee": "3.21",
"providerFee": "0",
"declineFee": "1.10",
"refundFee": "2.29",
"chargebackFee": "15.00",
"creditedAmount": "20.00",
"chargedAmount": "23.21"
}
Show at least chargedAmount, creditedAmount and the fee (processingFee) before the payer continues. processingFee is the whole fee and equals chargedAmount minus creditedAmount; providerFee is always 0 and kept for compatibility. declineFee, refundFee and chargebackFee are the fees that may be charged later if those outcomes occur.
If the selected amount would credit less than the route minimum, the quote endpoint
returns 400 with the calculated values in quote and the minimum valid value for
the selected amountMode in minimumInputAmount. Keep the linked amount visible,
show the minimum next to the field the payer edited, and do not create the deposit
until the next quote succeeds.
Step 3 - Create the Deposit #
Create the order using the quote's requestedAmount and expected values. Send a new, unique Idempotency-Key for each deposit intent.
curl -s -X POST "$PAYCA_BASE_URL/v2/accounts/$ACCOUNT_ID/deposits" \
-H "Content-Type: application/json" \
-H "x-client-id: $PAYCA_CLIENT_ID" \
-H "x-client-secret: $PAYCA_CLIENT_SECRET" \
-H "Idempotency-Key: order-20260813-0001" \
-d '{
"method": "card",
"amount": "20.00",
"expectedChargedAmount": "23.21",
"expectedCreditedAmount": "20.00",
"expectedPaycaFee": "3.21",
"expectedProviderFee": "0",
"expectedDeclineFee": "1.10",
"expectedRefundFee": "2.29",
"expectedChargebackFee": "15.00",
"country": "US",
"userId": "73f77d0f-8b30-46e8-9081-b506180f764e",
"payer": {
"email": "payer@example.com",
"firstName": "Alex",
"lastName": "Morgan",
"taxId": "123456789",
"dateOfBirth": "1990-04-12",
"city": "New York",
"postalCode": "10001",
"address": "123 Example Street"
},
"completeRedirectUrl": "https://app.example.com/deposits/complete",
"cancelRedirectUrl": "https://app.example.com/deposits/cancel"
}'
On a user's account userId may be omitted; if sent, it must be that user. On your own account, which is not bound to a user, name the payer with payerReference, your own stable id of the payer (1–128 characters, the same for the same person every time), and send payer in full with every deposit: such a payer is not a PayCA user and nothing is kept for them between requests. A deposit on your own account with neither payerReference nor userId is refused with 400.
For a payer's first deposit, send at least email and firstName, plus every other identity attribute you hold. A complete identity set allows screening to start through the API. For payment methods with a simplified profile flow, Payca may complete missing attributes server-side when the provider permits it. If full verification is required, the hosted checkout collects the additional information from the payer. A previously established payer identity may be reused, so payer can be omitted on later deposits for the same user.
Example 201 Created response:
{
"id": "f99bc4a6-604f-47a8-941b-6b02d4963504",
"status": "created",
"method": "card",
"accountId": "4a40c2a9-b145-4335-bf19-f302b9b72062",
"amount": "20.00",
"currency": "USD",
"providerFee": "0",
"paycaFee": "3.21",
"declineFee": "1.10",
"refundFee": "2.29",
"chargebackFee": "15.00",
"chargedAmount": "23.21",
"creditedAmount": "20.00",
"checkoutUrl": "https://checkout.example/deposit/f99bc4a6-604f-47a8-941b-6b02d4963504",
"createdAt": "2026-08-13T10:30:00Z"
}
Redirect the payer's full browser window to checkoutUrl. Do not embed or modify the hosted checkout URL.
created does not mean that the checkout URL is unavailable. A newly created deposit can already include checkoutUrl; when it does, redirect the payer immediately. Some funding routes may instead report awaiting_payment while waiting for the payer.
Creating a Deposit With Card Details #
When the option has cardDetailsRequired: true, add the payer's card and send the full payer profile:
curl -s -X POST "$PAYCA_BASE_URL/v2/accounts/$ACCOUNT_ID/deposits" \
-H "Content-Type: application/json" \
-H "x-client-id: $PAYCA_CLIENT_ID" \
-H "x-client-secret: $PAYCA_CLIENT_SECRET" \
-H "Idempotency-Key: order-20260929-0001" \
-d '{
"method": "card",
"amount": "100.00",
"expectedChargedAmount": "105.85",
"expectedCreditedAmount": "100.00",
"expectedPaycaFee": "5.85",
"expectedProviderFee": "0",
"expectedDeclineFee": "0",
"expectedRefundFee": "0",
"country": "DE",
"userId": "73f77d0f-8b30-46e8-9081-b506180f764e",
"payer": {
"email": "payer@example.com",
"firstName": "Alex",
"lastName": "Morgan",
"phone": "+4915112345678",
"dateOfBirth": "1990-04-12",
"city": "Berlin",
"postalCode": "10115",
"address": "Example Strasse 1",
"ipAddress": "203.0.113.7"
},
"card": {
"number": "4111111111111111",
"holder": "ALEX MORGAN",
"expiryMonth": "08",
"expiryYear": "2028",
"cvv": "737"
},
"completeRedirectUrl": "https://app.example.com/deposits/complete",
"cancelRedirectUrl": "https://app.example.com/deposits/cancel"
}'
- Payer profile. All of
firstName,lastName,email,phone(international format),dateOfBirth,city,address,postalCode, the top-levelcountryandipAddressare required. Attributes PayCA already holds for the user fill the gaps. Nothing is completed on your behalf, and a request with gaps is refused with400naming every missing field, before any order is written. ipAddress. The address of the payer's device as your server sees it — not one taken from a header the payer's browser can set.- Card. Only Visa and Mastercard are accepted.
numberis digits only,expiryMonthis01–12,expiryYearhas four digits,cvvhas three or four. A mistyped card is refused with400before any order is written. - Card data handling. Send the card only in this request, over TLS. Do not log it and never store the CVV. PayCA passes the card to the acquirer and keeps none of it.
The response depends on what the card issuer asks for:
- With 3-D Secure, the deposit carries a
checkoutUrl: the issuer's confirmation page. Redirect the payer's full browser window to it. The payer comes back tocompleteRedirectUrl, or tocancelRedirectUrlif the payment failed. - Without 3-D Secure, there is no
checkoutUrl. The outcome follows within seconds as the deposit's status: poll the deposit, or wait for the webhook.
A successful payment on these options is not credited at once. The deposit stays processing until the card acquirer settles the payment, by default four business days (Monday to Friday, UTC), and goes to completed when the account is credited. GET /v2/accounts/{accountId}/balance shows these deposits under settling.
Safe Retries #
If the create request times out, retry it with the same Idempotency-Key and unchanged body (card included, for card-details options). PayCA returns the original deposit instead of creating a second payable checkout or charging the card twice.
Use a new key when the account, amount, payer, country, or redirect URLs change. A reused key with a different request returns 409. A stale expected quote also returns 409; request a new quote and ask the payer to confirm the updated amounts.
Step 4 - Track the Result #
The browser may return before settlement finishes. Retrieve the order with:
curl -s "$PAYCA_BASE_URL/v2/accounts/$ACCOUNT_ID/deposits/$DEPOSIT_ID" \
-H "x-client-id: $PAYCA_CLIENT_ID" \
-H "x-client-secret: $PAYCA_CLIENT_SECRET"
Use GET /v2/accounts/{accountId}/deposits for history and reconciliation. It includes unsuccessful and in-progress attempts as well as completed deposits.
| Status | Meaning | Funds available? |
|---|---|---|
created |
PayCA recorded the order. A checkoutUrl may already be available; if it is, redirect the payer. |
No |
awaiting_payment |
The funding route reports that the checkout is waiting for the payer. | No |
processing |
Payment was confirmed but settlement or account credit is pending. | No |
completed |
Settlement was confirmed and the account credit was recorded. | Yes |
failed |
Payment failed. | No |
cancelled |
The checkout was cancelled. | No |
expired |
The checkout expired before payment completed. | No |
manual_review |
The order requires review before it can continue. | No |
refunded |
A previously paid deposit was refunded and its credit reversed. | No |
chargeback |
A previously paid deposit was charged back and its credit reversed. PayCA records it when the acquirer reports it. | No |
A paid deposit remains processing during its route's settlement window; on a card-details route that is by default four business days. Build against status transitions rather than a fixed timer.
Step 5 - Subscribe to Deposit Webhooks #
Register a webhook with type: deposit:
curl -s -X POST "$PAYCA_BASE_URL/v1/webhooks" \
-H "Content-Type: application/json" \
-H "x-client-id: $PAYCA_CLIENT_ID" \
-H "x-client-secret: $PAYCA_CLIENT_SECRET" \
-d '{
"url": "https://hooks.example.com/payca/deposits",
"type": "deposit"
}'
Example delivery:
{
"event": "account.deposit.completed",
"data": {
"id": "f99bc4a6-604f-47a8-941b-6b02d4963504",
"status": "completed",
"method": "card",
"accountId": "4a40c2a9-b145-4335-bf19-f302b9b72062",
"amount": "20.00",
"currency": "USD",
"chargedAmount": "23.21",
"creditedAmount": "20.00",
"providerFee": "0",
"paycaFee": "3.21",
"declineFee": "1.10",
"refundFee": "2.29",
"chargebackFee": "15.00",
"createdAt": "2026-08-13T10:30:00Z",
"completedAt": "2026-08-13T13:30:00Z"
}
}
Deposit events are:
account.deposit.completedaccount.deposit.failedaccount.deposit.cancelledaccount.deposit.expiredaccount.deposit.refundedaccount.deposit.chargebackaccount.deposit.manual_review
No webhook is sent for created, awaiting_payment, or processing; poll the deposit endpoint while an order is in flight. A deposit can move from completed to refunded or chargeback later, so keep processing deposit webhooks after the initial credit.
Verify x-signature before parsing the body and deduplicate deliveries by x-idempotency-key. See Webhook Handling Patterns for signature and replay details.
Fees and Reconciliation #
processingFee/paycaFeeis the whole deposit fee, quoted and fixed when the order is created.providerFeeis always0.- When creating the order you may echo the fee back either as
expectedPaycaFeealone or together withexpectedProviderFee0; an older split of the same total is accepted too. declineFeeis the fee charged separately after a decline.refundFeeis the fee charged separately after a refund.chargebackFeeis the fee charged separately after a chargeback. PayCA records the chargeback when the acquirer reports it; you receiveaccount.deposit.chargebackas for any other status.- Each of these fees is a percentage of the credited amount, a fixed amount, or both, and is fixed when the order is created. A fee that does not apply is
0. It is taken from the account's available balance; what the balance cannot cover is recorded as fee debt. - On
completed, reconcilecreditedAmountagainst the account balance. - On
refundedorchargeback, reverse the previously recognised deposit in your own ledger and reconcile the current PayCA account balance.
Common Errors #
| HTTP status | Meaning | Action |
|---|---|---|
400 |
Invalid amount, unsupported route, missing identity, invalid card details, or redirect URL not allow-listed. The acquirer refusing the payment request is reported as 400 too. |
Correct the request or contact PayCA to update the client configuration. |
403 |
Deposits are not enabled for this client. | Ask your PayCA account manager to enable card deposits. |
404 |
The account or deposit does not exist for this client. | Verify IDs and tenant ownership. |
409 |
Idempotency key conflicts with another request, or the expected quote changed. | Reuse the original body, or requote and create a new intent. |
Integration Checklist #
- Use
funding-optionsas the source of truth for availability and limits. - Check
cardDetailsRequiredon the option: redirect to hosted checkout, or collect the card yourself. - For card-details options: send the full payer profile and the device IP, and never store or log card data.
- Display the quote before redirecting the payer.
- Send the expected quote fields on create.
- Generate and persist one idempotency key per deposit intent.
- Use only allow-listed complete and cancel redirect URLs.
- Never credit funds based on the browser redirect.
- Treat only
completedas an available balance credit. - Handle later
refundedandchargebackevents. - Reconcile deposit history and the PayCA account balance.