Skip to main content

Prepaid cards

A prepaid card is requested with its own endpoints, because it works differently from a normal card:

  • The card is not ready at once. So the request does not return a card. It returns a prepaidRequestId and status: "PENDING". The card is created in the background, usually in 2-3 minutes, and you ask for the status of the request until it is finished.

Endpoints​

CardForEndpointProduct
VirtualIndividualPOST /individual/accounts/{id}/cards/prepaid/virtualR008
PhysicalIndividualPOST /individual/accounts/{id}/cards/prepaid/physicalR007
VirtualB2B cardholderPOST /business/cardholders/{id}/cards/prepaid/virtualR008
PhysicalB2B cardholderPOST /business/cardholders/{id}/cards/prepaid/physicalR007

{id} is the individual's _id, or the B2B cardholder's _id. If it does not belong to your partner, the answer is 404.

The product is fixed for each endpoint. You can leave productCode out; if you send it, it must match the table. For a B2B cardholder, the product must also be assigned to the company (see GET /business/accounts/{b2bAccountId}/products).

Prepaid virtual card​

The body is optional. Every field has a default.

FieldRequiredMeaning
productCodenoOnly R008. This is the default.
currencyCodenoOnly EUR. This is the default.
nicknamenoA name for the card, shown in your own screens.

Smallest request (empty body):

{}

Request with a nickname:

{
"nickname": "Online shopping"
}

Prepaid physical card​

A physical card is shipped and costs money, so it needs more information.

FieldRequiredMeaning
deliveryMethodyesHow the card is sent (carrier). An object; only _id is required. See below.
phoneNumberyesContact phone for the delivery.
countryyesCountry used for the fee when there is no deliveryAddressId. See below.
embossName1yesFirst line printed on the card (up to 22 characters).
embossName2noSecond line printed on the card (up to 19 characters).
deliveryAddressIdnoWhere the card is sent. A saved address of the cardholder. See below.
debitAccountNumbernoThe main account (IBAN) the fees are charged from. See below.
nicknamenoA name for the card.
productCodenoOnly R007. This is the default.

The delivery fee is not taken only from deliveryMethod. Both of these matter:

InputRole for the fee
deliveryMethod._idChooses the carrier (DHL or Poczta Post). That picks which fee rule is used (express vs normal). For some DHL cases a price from that method’s record is also added.
Delivery countryChooses EEA vs non-EEA pricing. Taken from the saved address when deliveryAddressId is sent; otherwise from the country field.

So: deliveryMethod = how it is sent; country / address = where, and that where affects the price.

deliveryMethod: how the card is sent​

  1. Ask which methods exist for a country: GET /fees/delivery-methods?country=BG (two-letter country code). That list only shows which carriers/methods are available for that country — it is not the final charged fee by itself.
  2. Take the _id of the method you want and send it:
"deliveryMethod": { "_id": "dhl-air-1" }

Only _id is required. The carrier is read from the start of the _id (dhl-… is DHL, pp_poczta-… is Poczta Post). deliveryType, pinDeliveryType, methodFields and price are optional; any price you send is not used as the charged fee — the server calculates the fee again.

deliveryAddressId: where the card is sent​

  • Left out: the card goes to the cardholder's registered address. Most requests do this. The fee then uses the country field.
  • Sent: the card goes to that saved address, and that address’s country is used for the fee. The country field is then ignored for pricing.

country​

Required. Used for the delivery fee when you do not send deliveryAddressId. Send the country of the registered address (ISO 3166-1 alpha-3, for example BGR).

debitAccountNumber: who pays the fees​

The card issuing fee and the delivery fee are charged from a main account of the cardholder (for a B2B cardholder, an account of the company).

  • Sent: that account is used. It must belong to the cardholder (or the company), otherwise the request is refused with 400.
  • Left out: the default main account is used.

Example: smallest valid request​

{
"deliveryMethod": { "_id": "dhl-air-1" },
"phoneNumber": "+359888123456",
"country": "BGR",
"embossName1": "ANA IVANOVA"
}

The card goes to the registered address, and the fees are charged from the default main account.

Example: full request​

{
"productCode": "R007",
"nickname": "Travel card",
"deliveryMethod": { "_id": "pp_poczta-6836df4c98653594cae54d72" },
"phoneNumber": "+359888123456",
"country": "BGR",
"deliveryAddressId": "onboarding:6836df4c98653594cae54d99",
"embossName1": "ANA IVANOVA",
"embossName2": "ACME LTD",
"debitAccountNumber": "BG09TRUD40059780001111"
}

The answer​

Both kinds of card answer the same way, with HTTP 200:

{
"message": "Prepaid physical card requested. The card will be created in a few minutes (2-3 minutes).",
"data": {
"prepaidRequestId": "6840a1f2c3d4e5f6a7b8c9d0",
"cardKind": "physical",
"cardholderId": "6836df4c98653594cae54d72",
"productCode": "R007",
"currency": "EUR",
"status": "PENDING"
}
}

status: "PENDING" means the request was accepted. It does not mean the card exists yet. Keep the prepaidRequestId: you use it to check the status.

Fees of a physical card​

The fees are handled in two steps, so the cardholder cannot spend the money while the card is being prepared:

  1. When you call the endpoint, the card issuing fee and the delivery fee are blocked on the main account. If the account does not have enough money, the request is refused with 400 and nothing is blocked.
  2. When the card is created, the blocked fees are charged. If the card cannot be created, the fees are unblocked.

To show the price before you request the card, use POST /fees/issuing-fee and POST /fees/delivery-fee. For a prepaid card use ProductType R007 and CustomerType Consumer Prepaid (individual) or Business Prepaid (B2B cardholder).

Check the status of a request​

The request answers right away, but the card is created later. To know where the request is, ask for its status:

EndpointWhat it returns
GET /individual/accounts/{id}/cards/prepaid/{requestId}One request of an individual
GET /individual/accounts/{id}/cards/prepaidAll the requests of an individual, newest first (up to 100)
GET /business/cardholders/{id}/cards/prepaid/{requestId}One request of a B2B cardholder
GET /business/cardholders/{id}/cards/prepaidAll the requests of a B2B cardholder, newest first (up to 100)
GET /cards/prepaidAll the requests of all your cardholders (individuals and B2B), newest first

GET /cards/prepaid needs no cardholder id. Each item has a cardholderId, and you can use page and limit.

{requestId} is the prepaidRequestId from the answer. A request that does not exist, or belongs to another cardholder, is a 404.

Statuses​

A request has one of three statuses. SUCCESS and FAILED are final.

statusisFinishedWhat it means
PENDINGfalseThe card is not ready yet. The request is being processed, usually for 2-3 minutes.
SUCCESStrueThe card is ready. cardKey is the key of the card.
FAILEDtrueThe request could not be completed. Contact PayNovus support (see below).

Ask again every few seconds/minutes, and stop when isFinished is true.

In progress:

{
"data": {
"prepaidRequestId": "6840a1f2c3d4e5f6a7b8c9d0",
"cardKind": "physical",
"cardholderId": "6836df4c98653594cae54d72",
"productCode": "R007",
"currency": "EUR",
"status": "PENDING",
"isFinished": false,
"statusMessage": "The card is being created. This usually takes 2-3 minutes.",
"cardKey": null,
"feesReleased": false,
"createdAt": "2026-10-08T10:15:00.000Z",
"statusUpdatedAt": "2026-10-08T10:17:10.000Z"
}
}

Finished: status is SUCCESS, isFinished is true, and cardKey has the key of the new card. Use it with the /cards/{cardKey} endpoints.

Failed:

{
"data": {
"prepaidRequestId": "6840a1f2c3d4e5f6a7b8c9d0",
"cardKind": "physical",
"status": "FAILED",
"isFinished": true,
"statusMessage": "The request could not be completed. For more information, please contact PayNovus support and give the prepaidRequestId.",
"cardKey": null,
"feesReleased": true
}
}

A failed request does not say why. For more information, contact PayNovus support and give the prepaidRequestId. A failed request is not retried by itself.

For a physical card, feesReleased: true means the fees that were blocked for the card were unblocked.

You can also find the finished card in the card list of the cardholder: GET /individual/accounts/{id}/cards or GET /business/cardholders/{id}/cards.

No webhook yet

You are not notified when the card is ready. Ask for the status of the request.

Load a prepaid card​

A prepaid card spends only the money loaded on it. You load it from a main account of the card's owner:

  • a card of an individual is loaded from the individual's own accounts;
  • a card of a B2B cardholder is loaded from the company's accounts.

The money never moves between two owners.

EndpointWhat it does
GET /cards/{cardKey}/prepaid/load-optionsThe card and its balance, and the accounts it can be loaded from
POST /cards/{cardKey}/prepaid/loadsLoads the card
GET /cards/{cardKey}/prepaid/loads/{loadId}One load: ask for it until it is finished
GET /cards/{cardKey}/prepaid/loadsThe loads of the card, newest first
  1. Ask for the load options. Each item of sourceAccounts is an account the card can be loaded from, with its availableBalance. The default account is first.
  2. Load the card with the id of the account as sourceAccountId:
{
"sourceAccountId": "6836df4c98653594cae54d80",
"amount": "25.00",
"idempotencyKey": "3f6c2a1e-9b7d-4c1a-8e2f-5d4b3a2c1e0f"
}

amount has at most two decimals. idempotencyKey is required: make a new one (e.g. a UUID) for each load. If you send a key you already used, the answer is 409 with code: "LOAD_ALREADY_EXISTS" and nothing is paid again. The key is checked against your own loads only.

  1. Ask for the load until it is finished. The answer of step 2 is 201 with the load:
statusWhat it means
SUBMITTEDThe bank accepted the payment and is booking it, usually in a few seconds.
SUCCESSThe money is on the card. Final.
FAILEDThe payment was not made. No money moved. Final.
UNCONFIRMEDThe bank did not answer, so the money may or may not have moved. PayNovus checks it. Do not load the card again.

While a load of the card is not finished, a new load of the same card is refused with 409.

Balance of prepaid cards​

GET /cards/prepaid/balances?cardKeys=a,b,c returns the money on each card, up to 50 cards per request:

{
"data": [
{ "cardKey": "1000234567", "found": true, "currency": "EUR", "availableBalance": 25.5 },
{ "cardKey": "1000234568", "found": false, "currency": null, "availableBalance": null, "message": "Card not found" }
]
}

found: false means the card does not exist, is not a prepaid card, or is not one of yours. availableBalance: null means the balance could not be read right now; it is not zero.

Common errors​

StatusWhy
400The product is not allowed (wrong code, or not assigned to the company).
400Not enough money on the main account for the card fees (physical card).
400The prepaid physical card limit is reached. This limit is separate from the limit of normal physical cards.
400deliveryMethod is not valid, the delivery address is not valid, or debitAccountNumber is not an account of the cardholder.
400A required field is missing (phoneNumber, country, embossName1, deliveryMethod).
404The individual or cardholder does not belong to your partner.
409Load: you already used the idempotencyKey, a load of the card is not finished yet, or the card can not be loaded right now.
422Load: not enough money in the source account. Nothing was paid.

See the full request and answer shapes in the API reference: Individual accounts → and Business accounts (B2B) →.