KashierDevelopersKashier Developers
Accept payments

Recurring payments

Save a card token once, then charge it each billing cycle

Charge a customer on a schedule by saving their card once. There are two phases:

  • Initial setup — the customer pays and you store the returned token.
  • Recurring charges — you charge that token each cycle.

The customer is involved only in the first payment.

There is no subscriptions API

Kashier does not offer a managed subscriptions or billing-plans API. You own the billing schedule: save a card token once, then charge it yourself each cycle with the Pay with Token API.

APIs used

  • Save Token API — initiates the recurring flow, displays the payment UI, and creates the token and agreement.
  • Pay with Token API — charges the customer using previously generated credentials.

Phase 1: Initial setup (Save Token API)

Step 1: Initiate setup

The merchant backend calls the Save Token API to start the recurring flow and show the Kashier payment UI.

Step 2: Customer completes payment

The customer enters card details and completes the payment. Kashier generates:

  • cardDataToken
  • agreementId

Step 3: Receive webhook

After a successful payment, Kashier sends a webhook containing the cardDataToken and agreementId.

Step 4: Store credentials

The merchant validates the webhook and securely stores the token and agreement data.

Phase 2: Recurring charges (Pay with Token API)

interactionSource changes between phases

interactionSource is RECURRING while saving the token during setup (see the Save Token field reference) and CONTAUTH while charging the stored token (see the Pay with Tokens field reference).

Step 5: Charge customer

For each subscription cycle, the merchant calls the Pay with Token API using the stored cardDataToken and agreementId.

Step 6: Handle result

Kashier processes the charge and returns the payment result. The merchant updates the subscription status accordingly.

Summary

  1. Call the Save Token API
  2. Customer completes payment
  3. Receive webhook with token and agreement
  4. Store credentials
  5. Use the Pay with Token API for recurring billing

Download the Kashier recurring APIs Postman collection

List tokens

Parameters

ParameterTypeDescription
sortTypeQuery ParameterUsed to sort the results (-1 = DESC, 1 = ASC).
pageQuery ParameterCurrent page number (used for pagination).
limitQuery ParameterNumber of items per page (used for pagination).

Headers

KeyDescription
AuthorizationThe Authorization is the secret key that is used to identify the merchant. You can obtain it from the Kashier dashboard. Learn more about Authorization.
curl --location 'https://test-api.kashier.io/v3/payment/tokenization/tokens?sortType=-1&page=1&limit=20'
     --header 'Authorization: YOUR_TEST_SECRET_KEY'

Response structure

{
  "message": "success",
  "data": [
      {
          "cardHolderName": "Hegab",
          "token": "a559ecc6-11a2-431a-b40c-c10df4e7a9df",
          "agreementId": "65d4717c2b2c17002469e463",
          "customerReference": "12345",
          "agreementType": "UNSCHEDULED",
          "agreementExpiry": "N/A",
          "cardNumber": "5123********2346"
      },
      {
          "cardHolderName": "Hussein Mo",
          "token": "efca2dc1-ea90-480b-99ae-00f072fbc516",
          "agreementId": "668bc3b9b2c0fe0024a37af0",
          "customerReference": "12345",
          "agreementType": "UNSCHEDULED",
          "agreementExpiry": "2024-12-13T13:32:05.000Z",
          "cardNumber": "5123********0008"
      },
      {
          "cardHolderName": "TEST",
          "token": "c34faed2-b1e3-4ebf-99ab-992ef2f70d61",
          "agreementId": "66043d39ec69ad0024b9c012",
          "customerReference": "123456",
          "agreementType": "RECURRING",
          "agreementExpiry": "2024-11-14T15:47:29.448Z",
          "cardNumber": "5078********5581"
      }
  ],
  "pagination": {
      "total": 3,
      "limit": 20,
      "page": 1,
      "pages": 1
  }

}

RECURRING vs UNSCHEDULED agreement types

The response above shows tokens with agreementType set to both RECURRING and UNSCHEDULED — the same values appear as agreement.type in the Save token request example. What's confirmed is that both are valid agreement.type / agreementType values:

ValueConfirmed meaning
RECURRINGA scheduled recurring agreement — billed on a fixed schedule (see paymentFrequency in the Save token example).
UNSCHEDULEDA card-on-file agreement without a fixed billing schedule.

Beyond this, no further guidance on choosing between the two is documented — treat the table above as what's confirmed, not a complete decision guide.

Save token

Saving a card is a payment session create call with an agreement object and saveCard set — the session renders the payment UI, and the token and agreement come back on the webhook once the customer pays.

Headers

KeyDescription
AuthorizationYour Secret Key, used to identify the merchant. You can obtain it from the Kashier dashboard. Learn more about Authorization.
api-keyYour Payment API Key, from the merchant dashboard under the Integrations section. It differs between the test and live environments.
Content-Typeapplication/json
curl --location 'https://test-api.kashier.io/v3/payment/sessions'

--header 'Authorization: YOUR_TEST_SECRET_KEY'
--header 'api-key: YOUR_TEST_API_KEY'
--data '{
"expireAt": "2027-10-31T17:27:32.359Z",
"maxFailureAttempts": 3,
"paymentType": "credit",
"amount": "1",
"currency": "EGP",
"merchantId": "MID-XXXXX-XXX",
"merchantOrderId": "ORD-123456",
"merchantRedirect": "https://your-website.com/redirect",
"display": "en",
"type": "one-time",
"allowedMethods": "card",
"redirectMethod": null,
"iframeBackgroundColor": "#FFFFFF",
"metaData": {
"customKey": "customValue"
},
"failureRedirect": false,
"brandColor": "#FF5733",
"defaultMethod": "card",
"description": "Payment for order ORD-123456",
"manualCapture": false,
"customer": {
"reference": "ahmed"
},
"agreement": {
"type": "RECURRING",
"amountVariability": "VARIABLE",
"paymentFrequency": "MONTHLY",
"expiryDate": "2027-01-27",
"minimumDaysBetweenPayments": 20,
"maximumAmountPerPayment": 20000,
"numberOfPayments": 100
},
"saveCard": "forced",
"retrieveSavedCard": true,
"interactionSource": "RECURRING",
"enable3DS": true,
"serverWebhook": "https://your-website.com/kashier-webhook",
"notes": "test"
}'

Body description

Response structure

{
  "status": "CREATED",
  "failureAttempts": 0,
  "capturedAmount": 0,
  "refundedAmount": 0,
  "_id": "67adc07584f10c00121f6739",
  "merchantId": "MID-XXXXX-XXX",
  "expireAt": "2027-10-31T17:27:32.359Z",
  "maxFailureAttempts": 3,
  "paymentParams": {
    "paymentType": "credit",
    "amount": "1",
    "currency": "EGP",
    "merchantOrderId": "ORD-123456",
    "merchantRedirect": "https://your-website.com/redirect",
    "display": "en",
    "type": "one-time",
    "allowedMethods": "card",
    "customer": { "reference": "ahmed" },
    "agreement": {
      "type": "RECURRING",
      "amountVariability": "VARIABLE",
      "paymentFrequency": "MONTHLY",
      "expiryDate": "2027-01-27",
      "minimumDaysBetweenPayments": 20,
      "maximumAmountPerPayment": 20000,
      "numberOfPayments": 100
    },
    "saveCard": "forced",
    "retrieveSavedCard": true,
    "interactionSource": "RECURRING",
    "enable3DS": true,
    "serverWebhook": "https://your-website.com/kashier-webhook"
  },
  "history": [
    { "status": "CREATED", "date": "2026-08-25T09:50:45.360Z" }
  ],
  "webhookNotifications": [],
  "createdAt": "2026-08-25T09:50:45.363Z",
  "updatedAt": "2026-08-25T09:50:45.363Z",
  "sessionUrl": "https://payments.kashier.io/session/67adc07584f10c00121f6739?mode=test"
}

Send the customer to sessionUrl — or render it in an iframe, as in payment sessions. The session is created in CREATED state; no card is saved and no token exists yet.

The token arrives on the webhook, not here

This call only creates the session. The cardToken and the confirmed agreement are delivered to your serverWebhook once the customer completes payment — see webhook payloads. Do not expect a token in this response.

Pay with tokens

Headers

KeyDescription
Kashier-HashOrder hash generated in hashing. Append .{customerReference} to the signed string — it is required whenever card.save, card.cardToken, or card.agreement is present.
curl --location 'https://test-fep.kashier.io/v3/orders'

--header 'kashier-hash: {{hash}}'
--header 'Content-Type: application/json'
--data '{
"apiOperation":"PAY",
"paymentMethod":{
"type":"CARD",
"card":{
"agreement":{
"id":"03c331af-88b5-47ed-be28-6c671e760d5c"
},
"enable3DS":false,
"cardToken":"c3a64de8-c172-40e6-8412-0bb2e2b7e895"
}
},
"order":{
"reference":"PM-1756736464046963252",
"amount":100,
"currency":"EGP"
},
"shipping":{
"address":{
"city":null,
"company":null,
"country":null,
"postcodeZip":null,
"source":null,
"stateProvince":null,
"stateProvinceCode":null,
"street":null,
"street2":null,
"sameAsBilling":true
},
"method":"",
"origin":{
"postcodeZip":""
}
},
"billing":{
"address":{
"city":null,
"company":null,
"country":null,
"postcodeZip":null,
"source":null,
"stateProvince":null,
"stateProvinceCode":null,
"street":null,
"street2":null
}
},
"interactionSource":"CONTAUTH",
"reconciliation":{
"webhookUrl":"https://your-call-back-url.com",
"merchantRedirect":"https://your-call-back-url.com"
},
"merchantId":"MID-XXXXX-XXX",
"customer":{
"reference":"12345963852"
}
}'

Full parameter and response reference → Pay with token.

Bulk charge

Bulk charge is off until Kashier enables it

Bulk charge is gated by the per-merchant bulk charge feature flag. While it is off, both bulk-charge endpoints reject the request with 400 and the message key message.bulk.charge.disabled, even though your secret key is valid. A new merchant account starts with only a small default set of features enabled, so assume bulk charge is off until you have asked Kashier ops to turn it on.

Headers

KeyDescription
AuthorizationThe Authorization is the secret key that is used to identify the merchant. You can obtain it from the Kashier dashboard. Learn more about Authorization.
curl --location 'https://test-api.kashier.io/v3/payment/bulk-charge'
  --header 'Authorization: YOUR_TEST_SECRET_KEY'
  --form 'file=@"/home/k/Downloads/tokens_export.xlsx"'

Response structure

{
  "message": "success"

}

Bulk charge runner

Headers

KeyDescription
AuthorizationThe Authorization is the secret key that is used to identify the merchant. You can obtain it from the Kashier dashboard. Learn more about Authorization.
curl --location 'https://test-api.kashier.io/v3/payment/bulk-charge/runner'
  --header 'Authorization:  YOUR_TEST_SECRET_KEY'

Response structure

{
  "message": "success"

}

Export tokens

Headers

KeyDescription
AuthorizationThe Authorization is the secret key that is used to identify the merchant. You can obtain it from the Kashier dashboard. Learn more about Authorization.
curl --location 'https://test-api.kashier.io/v3/payment/tokenization/tokens/export'
  --header 'Authorization: YOUR_TEST_SECRET_KEY'

Response structure

The response is a file that will be automatically downloaded in your browser.

Delete token

Headers

KeyDescription
AuthorizationThe Authorization is the secret key that is used to identify the merchant. You can obtain it from the Kashier dashboard. Learn more about Authorization.
curl --location --request DELETE 'https://test-api.kashier.io/v3/payment/tokenization/tokens/:token'
  --header 'Authorization: YOUR_TEST_SECRET_KEY'

Response structure

{
  "message": "success"

}

On this page