KashierDevelopersKashier Developers
Direct API integration

Installment plans

List installment banks and plans, pay with a selected plan, and see the standalone BNPL providers (valU, Octo, Souhoola, Contact, Mogo, Tru, Forsa)

To retrieve installment plans and pay with one:

Step 1: Get available banks

EndpointValue
URLhttps://test-api.kashier.io/merchant/installments/banks/plans?mid=yourMerchantID&amount=productPrice
MethodGET

Whenever you are ready for production, use the following production API endpoint URL instead.

EndpointValue
URLhttps://api.kashier.io/merchant/installments/banks/plans?mid=yourMerchantID&amount=productPrice
MethodGET
curl -X 'GET'
  'https://test-api.kashier.io/merchant/installments/banks/plans?mid=MID-0000-000&amount=500'

Full parameter and response reference → Get available banks.

Query parameters

ParameterRequiredNotes
midYesYour merchant ID.
amountYesThe product price, used to filter out plans whose minimum the order doesn't meet.
clientTypeNoSending POS removes QNB and Banque Misr from the returned bank list.

minimunInstallmentAmount is misspelled on the wire

This step returns each bank's minimum as minimunInstallmentAmount — the missing second m is genuinely part of the wire key, not a typo in these docs. Step 2 returns the same value under a different name, Minimum installment amount. Handle both spellings across the two steps.

allowFawry

allowFawry may still appear in this response, but as far as we can confirm nothing routes to Fawry today: the provider is implemented in Kashier's payment-object layer, yet it has no entry in the payment routing tables that back the /v3/orders flow, so there is no Fawry equivalent of the Basata reference-code path. Confirm with Kashier support before planning a Fawry integration or building against the flag.

BNPL availability flags

Alongside banks, the response carries boolean flags showing which BNPL providers are available for the merchant, computed from real provisioning for that merchant:

FlagEnabled when
allowValuvalU is provisioned for the merchant
allowOctoOcto is provisioned for the merchant
allowSouhoolaSouhoola is enabled for the merchant

These BNPL providers use their own dedicated payment flow — they are not paid via the installments.planId card path described in Step 3 below.

Step 2: Get plans for a specific bank

EndpointValue
URLhttps://test-api.kashier.io/merchant/installments/plans?mid=yourMerchantID&amount=productPrice&currency=EGP&fiId=banknSystemID
MethodGET

Whenever you are ready for production, use the following production API endpoint URL instead.

EndpointValue
URLhttps://api.kashier.io/merchant/installments/plans?mid=yourMerchantID&amount=productPrice&currency=EGP&fiId=banknSystemID
MethodGET
curl -X 'GET'
  'https://test-api.kashier.io/merchant/installments/plans?mid=MID-0000-000&amount=10000&currency=EGP&fiId=FI-13'

Full parameter and response reference → Get plans for specific bank.

Query parameters

ParameterRequiredNotes
midYesYour merchant ID.
amountYesThe product price.
currencyYesMust be EGP. Any other value is rejected with a hard 400 and the cause EGP.currency.is.required.in.installment — bank installments are EGP-only.
fiId or cardBinExactly onefiId is the Bank system ID from Step 1. cardBin is an accepted alternative: pass the customer's card BIN and Kashier resolves the bank for you. Sending both, or neither, is rejected with financial.institution.system.id.or.the.card.bin.is.required.
clientTypeNoSending POS returns a camelCase response shape that also carries interestAmount per plan, instead of the default Title Case online shape.

The response renames the Step 1 minimum: what Step 1 calls minimunInstallmentAmount is returned here as Minimum installment amount.

Step 3: Pay with a plan

Once you have a Merchant Plan ID (e.g. INSPLAN-53) from Step 2, pay with it by adding installments.planId to a normal card payment request. This is the same POST /v3/orders request used for any card payment — the plan is validated before the card is charged.

EndpointValue
URLhttps://test-fep.kashier.io/v3/orders/
MethodPOST

Whenever you are ready for production, use the following production API endpoint URL instead.

EndpointValue
URLhttps://fep.kashier.io/v3/orders/
MethodPOST
curl -X 'POST' 'https://test-fep.kashier.io/v3/orders/' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'Kashier-Hash: your_generated_hash' \
  -d '{
      "apiOperation": "PAY",
      "installments": {
          "planId": "INSPLAN-53"
      },
      "paymentMethod": {
          "type": "CARD",
          "card": {
              "number": "5484571234560000",
              "expiry": {
                  "month": "05",
                  "year": "26"
              },
              "nameOnCard": "TEST",
              "securityCode": "100"
          }
      },
      "order": {
          "reference": "PM-89451648984",
          "amount": "10000",
          "currency": "EGP",
          "description": ""
      },
      "interactionSource": "ECOMMERCE",
      "reconciliation": {
          "webhookUrl": "https://your-call-back-url.com",
          "merchantRedirect": "https://your-call-back-url.com",
          "redirect": true
      },
      "customer": {
          "reference": "24"
      },
      "merchantId": "MID-0000-000"
  }'

Body parameters

ParameterDescription
installments.planId (string)The Merchant Plan ID from Step 2 (e.g. INSPLAN-53). Matched against the plan copy enabled for your account. Omit installments entirely for a regular (non-installment) card payment.
paymentAgreementSet by Kashier, not by you. Omit installments and the request is treated as regular; send installments and it becomes installment.

How the plan is validated

When installments is present, the payment is treated as an installment agreement (as opposed to a regular card charge), and the plan is validated before the card is charged:

  1. installments.planId must match a known master plan. This check runs in every mode, test included.
  2. The plan must be active.
  3. The card's BIN must fall inside the plan's binRanges (the same ranges returned as Supported BINs in Step 2).
  4. The plan must actually be provisioned and active for your merchant account.

If any check fails, the request is rejected before the card is charged, with one of the error codes below.

Validate the card BIN against Supported BINs in your own UI before submitting, so the customer is not shown a plan their card cannot use.

What test mode does and doesn't skip

Only the active-plan and BIN-range checks are gated on live mode — checks 2 and 3 above don't run in test. The master-plan lookup in check 1 still runs, so an unknown planId returns PLAN_NOT_EXIST in test just as it does live. If your merchant copy of a valid plan is missing, test mode synthesizes a default copy with zero fees and planFinancing: true, so a test payment can succeed on a plan that would be rejected live.

Pay-time errors

CodeMeaningFix
PLAN_NOT_EXISTNo plan matches the planId you sent, or your account has no copy of it.Re-read the plan list from Step 2 and send a Merchant Plan ID from the current response.
PLAN_NOT_ACTIVEThe plan exists but is not active.Pick another plan, or ask Kashier support to activate it for your account.
INVALID_BIN_RANGEThe card BIN is outside the plan's supported ranges.Ask the customer for a card from the bank that owns the plan, or offer a different plan.
INVALID_MERCHANT_PLANThe plan does not belong to your merchant account.Use only plans returned for your own mid.

Response

Once validation passes, the normal card payment flow runs unchanged — including 3DS, capture, and the response shape. See Customized card form for the full response structure, and 3D Secure handling for the 3DS redirect flow.

You can find how much the customer will pay monthly for every plan in the Installment amount per month parameter of the Step 2 response.

BNPL installment providers

Beyond bank card installments (Steps 1–3 above), Kashier supports several standalone BNPL (buy-now-pay-later) providers. Each is its own paymentMethod.type, with its own dedicated payment flow — none of them are paid via the installments.planId card path.

ProviderpaymentMethod.typeProvider type(s)
valUvaluvalu (online), valupos (POS)
Octooctoocto
Souhoolasouhoolasouhoola
Contactcontactcontact, contact_pos
Mogomogomogo, mogo_pos
Trutrutru
Forsaforsaforsa, forsa_pos

Availability

Of these, three are surfaced as availability flags on the Step 1 banks responseallowValu, allowOcto, and allowSouhoola. Mogo, Tru, Forsa, and Contact don't have a documented availability flag of their own on that response; whether one of them is usable for a given merchant depends on that merchant's own provisioning rather than a flag here.

Contact

Contact (paymentMethod.type: "contact", provider contact online / contact_pos on POS) is a BNPL provider, not a cash or kiosk method. It's initiated with get_categories / validate_balance and then progresses through tenure selection, OTP, pay, and refund (including a dedicated otp_refund step).

On this page