Statira API
Build payments
that settle perfectly.
Use Statira's REST API to create hosted payment sessions, accept cards, bank transfers and USSD, and confirm every transaction from your server.
Keep secret keys on your server
Every gateway request requires the public and secret keys created in your Statira Business dashboard. Send them using X-Public-Key and X-Secret-Key. Never expose the secret key in browser or mobile code.
Connect your store securely
- Sign in to the merchant dashboard for TEST or LIVE. Open Settings → Create API key and choose the permissions your store needs.
- For wallet transfers, select
wallet.payoutandwallet.view. Configure the calling server’s IP whitelist on the key. - Your store starts hosted login with URL-encoded
site_urlandredirect_url. The merchant signs in and selects the API key to connect. - Exchange the returned
zijelapay_connect_codefrom your server atPOST /api/v1/ecommerce/connect/exchange. The code expires after five minutes and is single-use. - Store
data.opaqueKeysecurely and send it asX-Ecommerce-Keyto e-commerce endpoints. It inherits the selected key’s permissions, IP restrictions, and environment.
An e-commerce key is separate from a public/secret-key pair or partner onboarding credentials. It must never be embedded in browser code.
Create a checkout with your e-commerce key
Your server sends its zec_... key as X-Ecommerce-Key. The underlying API key needs payment.create and payment.verify. Keep the key on your server.
/api/v1/ecommerce/payments/intentscurl --request POST \
--url 'https://api.paywithstatira.com/api/v1/ecommerce/payments/intents' \
--header "X-Ecommerce-Key: $STATIRA_ECOMMERCE_KEY" \
--header 'Content-Type: application/json' \
--data '{
"merchantReference": "ORDER-1001",
"amountMinor": 250000,
"currencyCode": "NGN",
"customerEmail": "customer@example.com",
"customerName": "Jane Doe",
"description": "Payment for order ORDER-1001",
"callbackUrl": "https://shop.example.com/payment/callback"
}'250000 represents ₦2,500.00. Save your order reference, data.id, and data.reference, then redirect the customer to the exact data.hostedCheckoutUrl returned. Sessions default to 60 minutes; sessionDurationMinutes can override this within 5–1440 minutes. Inspect data.amountQuotes for the fees and final charge.
Optional feeBearer accepts CUSTOMER or MERCHANT; omitting it uses configured fee handling. For testing, use https://api.dev.paywithstatira.com with a TEST connection key.
Verify the transaction before fulfilment
The HTTPS callbackUrl receives the browser return with reference, status, and your merchantReference when provided. Verify the reference from your server; browser parameters alone are not proof of payment.
/api/v1/ecommerce/payments/verify/{reference}curl --request GET \
--url 'https://api.paywithstatira.com/api/v1/ecommerce/payments/verify/TXN_REPLACE_WITH_TRANSACTION_REFERENCE' \
--header "X-Ecommerce-Key: $STATIRA_ECOMMERCE_KEY"Use the TXN_... transaction reference, not the ALT_... intent reference, intent UUID, or order reference. Read data.transaction.status, data.transaction.internalReference, data.transaction.merchantReference, and data.transaction.capturedAmountMinor. Confirm SUCCESS and reconcile the order and expected charge before fulfilment. Process each order once.
A validated payment webhook can also confirm payment when the customer closes the browser. The callback URL is not a webhook endpoint.
Onboard and track your merchants
Use X-Partner-Id and X-Partner-Key with credentials issued by Statira for your environment. Partner keys manage your linked merchants; they do not authorize wallet spending.
- Call
POST /api/v1/partners/merchantswith a stableexternalUserId, owner details, and business details. Savedata.merchant.id. - If the owner already has a Statira merchant, use
/api/v1/partners/merchants/link-requestsand complete owner OTP consent. A different business under the same owner email needs resolution with Statira. - Upload the CAC certificate and representative identity to
/api/v1/partners/merchants/{externalUserId}/kyc/documents. Both must be approved; proof of business address is optional for now. - Complete the KYC profile and required related parties, check the KYC case for missing requirements, then submit it for review.
- Configure an email and signed webhook at
PUT /api/v1/partners/notificationsto receivemerchant.approved. Use the event’s external user ID to update your seller.
Download the partner onboarding API guide · Approval webhook and email contract
Test first, then go live
https://api.dev.paywithstatira.comUse TEST-mode API keyshttps://api.paywithstatira.comUse LIVE-mode API keysAmounts are integers in the currency's smallest unit. For NGN, 250000 represents ₦2,500.00.
Show the fee before confirmation
Quote the base amount before creating a payment or payout. Use CARD, BANK_TRANSFER, USSD, or PAYOUT as the rail, and a positive integer amountMinor.
/api/v1/gateway/fees/quotecurl --request POST \
--url https://api.paywithstatira.com/api/v1/gateway/fees/quote \
--header 'Content-Type: application/json' \
--header 'X-Public-Key: pk_live_your_key' \
--header 'X-Secret-Key: sk_live_your_key' \
--data '{"rail":"BANK_TRANSFER","amountMinor":50000}'Illustrative fee; merchant pricing varies{
"success": true,
"message": "Fee quote calculated",
"data": { "totalFeeAmountMinor": 500 },
"meta": {},
"correlationId": "example-correlation-id"
}Collection quotes require payment.create; payout quotes require wallet.payout. Use environment-matched keys. E-commerce integrations send the same body to /api/v1/ecommerce/fees/quote with X-Ecommerce-Key.
- The response contains only
totalFeeAmountMinor. It does not create a transaction, reserve funds, or guarantee a price. - For a ₦500 order and a ₦5 quote,
CUSTOMERpays ₦505 before provider charges;MERCHANTcollects ₦500 and receives ₦495. SetfeeBeareron the intent, not the quote request. - Intent
amountQuotesgive the rail breakdown. After generating payment instructions, displayexpectedAmountMinoras the final transfer amount; a provider may add a processing charge. - A payout quote gives the total fee you will pay. A ₦1,000 payout with a ₦30 fee needs ₦1,030 in the wallet; the beneficiary receives ₦1,000.
- Requote when the amount or rail changes. Example fees are not a fixed tariff.
Create a hosted checkout session
Create an intent from your server. Use a unique Idempotency-Key for each order so network retries cannot create duplicate payments.
/api/v1/gateway/payments/intentscurl --request POST \
--url https://api.paywithstatira.com/api/v1/gateway/payments/intents \
--header 'Content-Type: application/json' \
--header 'X-Public-Key: pk_live_your_key' \
--header 'X-Secret-Key: sk_live_your_key' \
--header 'Idempotency-Key: order_84392' \
--data '{
"merchantReference": "order_84392",
"amountMinor": 250000,
"currencyCode": "NGN",
"customerEmail": "customer@example.com",
"customerName": "Ada Okafor",
"description": "Order #84392",
"feeBearer": "CUSTOMER",
"callbackUrl": "https://yourapp.com/payments/complete"
}'The response includes reference, checkoutSessionToken, amountQuotes, hostedCheckoutUrl, status and expiresAt. Redirect your customer to hostedCheckoutUrl for the recommended integration.
Build a custom bank-transfer interface
Most merchants should use hostedCheckoutUrl. If you are building your own checkout UI, your backend takes the intent reference and initiates BANK_TRANSFER using the same public and secret API keys. The intent must belong to that merchant and key environment.
/api/v1/gateway/payments/intents/{intentReference}/paycurl --request POST \
--url https://api.paywithstatira.com/api/v1/gateway/payments/intents/ALT_1789416000000/pay \
--header 'Content-Type: application/json' \
--header 'X-Public-Key: pk_live_your_key' \
--header 'X-Secret-Key: sk_live_your_key' \
--data '{
"customerName": "Ada Okafor",
"customerEmail": "customer@example.com",
"paymentMethod": "BANK_TRANSFER",
"metadata": {
"orderId": "order_84392"
}
}'The response creates a transaction and returns its internalReference. Parse nextActionDataJson once to read accountNumber, accountName, bankName, expectedAmountMinor, providerFeeAmountMinor, currencyCode, expiresAt and instructions.
expectedAmountMinor. Do not display the original base amount or calculate provider charges locally.- Keep
internalReferencefor authenticated verification. - Do not generate multiple accounts by repeatedly submitting the same checkout.
- Wait for the signed webhook or verify from the backend; a customer saying they paid is not proof of payment.
Choose who pays per checkout
Set feeBearer to CUSTOMER or MERCHANT when creating the intent. Omit it only when you want the merchant's configured default for the selected rail.
CUSTOMER: customer pays the base amount plus the Statira fee; the merchant receives the base amount.MERCHANT: customer pays the base amount; the Statira fee is deducted from the merchant wallet credit.feeAmountMinorin each quote is the Statira fee.totalAmountMinoris the pre-provider customer total.- After account generation,
expectedAmountMinoris the final amount because the provider may add its own processing charge.
Confirm before delivering value
Always verify a transaction from your backend using its TXN_ internal transaction reference. The ALT_ intent reference is for payment initiation and returns 404 on verification. Do not rely only on the customer's browser redirect.
/api/v1/gateway/payments/verify/{reference}curl --request GET \
--url https://api.paywithstatira.com/api/v1/gateway/payments/verify/TXN_ABC123 \
--header 'X-Public-Key: pk_live_your_key' \
--header 'X-Secret-Key: sk_live_your_key'Read data.transaction.status from the response and verify the merchant reference and amounts before fulfilment. Only fulfil an order once its verified status is SUCCESS.
If a payment is PENDING, wait for an update or verify it again using the same transaction reference. Do not generate a replacement account simply because notification is delayed. If the customer has paid but the status remains pending, contact support with the transaction reference and response correlation ID.
For a custom bank-transfer or USSD checkout, an “I have paid” button can call POST /api/v1/public/checkout/status/{transactionReference}/confirm with no body to request an immediate check. It checks the existing payment and may still return PENDING. Hosted checkout handles this action; authenticated verification remains required before fulfilment.
Receive payment updates
Add an HTTPS webhook endpoint to an API key in Statira Business. Statira delivers payment.updated when a transaction changes. Verify the signature and durably accept the event before returning HTTP 2xx; heavier work can run asynchronously. Failed deliveries are retried up to three attempts.
payment.updated{
"event": "payment.updated",
"reference": "TXN_ABC123",
"merchantReference": "order_84392",
"status": "SUCCESS",
"mode": "LIVE",
"amountMinor": 250500,
"baseAmountMinor": 250000,
"feeBearer": "CUSTOMER",
"feeAmountMinor": 500,
"netAmountMinor": 250000,
"currencyCode": "NGN",
"paymentMethod": "BANK_TRANSFER",
"providerCode": "EMBEDLY",
"providerReference": "provider-reference",
"failureCode": null,
"failureMessage": null
}Collection statuses are CREATED, PENDING, PROCESSING, SUCCESS, FAILED, CANCELLED, EXPIRED, and REFUNDED. Only SUCCESS authorizes fulfilment.
payout.updated{
"event": "payout.updated",
"reference": "PAYOUT_1789416000000",
"status": "SUCCESS",
"mode": "LIVE",
"amountMinor": 100000,
"feeAmountMinor": 500,
"netAmountMinor": 100000,
"currencyCode": "NGN",
"providerCode": "FLUTTERWAVE",
"providerReference": "provider-payout-reference",
"failureCode": null,
"failureMessage": null
}Payout statuses are PENDING, SUCCESS, and FAILED. The wallet debit is amountMinor + feeAmountMinor; amountMinor is sent to the beneficiary.
wallet.funded{
"event": "wallet.funded",
"reference": "FUND_033511da032646d2a42f30d8f869b9b1",
"providerReference": "provider-transaction-reference",
"status": "SUCCESS",
"mode": "LIVE",
"amountMinor": 100000,
"currencyCode": "NGN",
"balanceAfterMinor": 350000
}wallet.funded is sent only when a bank transfer has credited your Statira wallet. balanceAfterMinor is the balance immediately after the credit.
- Verify
X-Zijelapay-Signatureas hex HMAC-SHA256 over the exact raw body using the endpoint secret. - Collection and payout scopes have separate URLs and signing secrets.
- Handle repeated deliveries idempotently. An earlier
PENDINGevent must not suppress a laterSUCCESSfor the same reference. Deduplicate fulfilment by transaction reference and process status changes. - Fetch collections from the authenticated verify endpoint before fulfilling an order.
Verify the account before transferring
With bank.verify, first call GET /api/v1/gateway/payouts/banks?countryCode=NG¤cyCode=NGN. Use a bank code returned by that directory; do not assume codes from another provider are interchangeable.
/api/v1/gateway/payouts/accounts/verifycurl --request POST \
--url https://api.paywithstatira.com/api/v1/gateway/payouts/accounts/verify \
--header 'Content-Type: application/json' \
--header 'X-Public-Key: pk_live_your_key' \
--header 'X-Secret-Key: sk_live_your_key' \
--data '{"bankCode":"000013","accountNumber":"0123456789"}'The response data contains bankCode, accountNumber, accountName, countryCode, currencyCode, and verified. Show the verified account name for confirmation, then use those details for the payout.
E-commerce equivalents are GET /api/v1/ecommerce/payouts/banks and POST /api/v1/ecommerce/payouts/accounts/verify, authenticated with X-Ecommerce-Key.
Transfer from a merchant wallet
Use a key matching the server environment with the wallet.payout permission: TEST on dev and LIVE on production. Every payout requires a unique Idempotency-Key; repeating the same key safely returns the original payout.
/api/v1/gateway/payoutscurl --request POST \
--url https://api.paywithstatira.com/api/v1/gateway/payouts \
--header 'Content-Type: application/json' \
--header 'X-Public-Key: pk_live_your_key' \
--header 'X-Secret-Key: sk_live_your_key' \
--header 'Idempotency-Key: payout_order_84392' \
--data '{
"destinationBankCode": "000013",
"destinationBankName": "GTBank",
"destinationAccountName": "Ada Okafor",
"destinationAccountNumber": "0123456789",
"amountMinor": 250000,
"narration": "Vendor settlement"
}'Quote PAYOUT first and ensure the available wallet balance covers amountMinor + totalFeeAmountMinor. The payout response reports the actual total fee in feeAmountMinor. Both amountMinor and netAmountMinor are the beneficiary amount.
Statira prefixes narration with your business name, for example Amina Stores/Vendor settlement. Send only the descriptive part. Blank narration uses Payout.
Recover a timeout without a second transfer
Read GET /api/v1/gateway/payouts/{payoutReference} using the PAYOUT_ reference. If the create request timed out before you received a reference, look up its original idempotency key:
/api/v1/gateway/payouts/by-idempotency-key/{idempotencyKey}curl --request GET \
--url https://api.paywithstatira.com/api/v1/gateway/payouts/by-idempotency-key/payout_order_84392 \
--header 'X-Public-Key: pk_live_your_key' \
--header 'X-Secret-Key: sk_live_your_key'These routes require wallet.payout and return only payouts belonging to the authenticated merchant. E-commerce callers use /api/v1/ecommerce/payouts/... with X-Ecommerce-Key. URL-encode the key in a lookup path.
404means no matching payout has been persisted. If the first request may still be running, wait and repeat the lookup.- Retry the same logical request with the same key. A new key can create another transfer.
- While a payout is
PENDING, wait for a webhook or check its status again. Do not submit a replacement transfer. SUCCESSsettles the hold;FAILEDreleases the reserved amount and fees. Processpayout.updatedand refresh the wallet balance after resolution.
Read the authoritative Statira balance
Use either authentication method from your backend. The wallet-transfer release also returns walletId, equal to id, for saving in your application. The response includes availableBalanceMinor, pendingBalanceMinor, totalCreditedMinor, and totalDebitedMinor.
/api/v1/gateway/walletcurl --request GET \
--url https://api.paywithstatira.com/api/v1/gateway/wallet \
--header 'X-Public-Key: pk_live_your_key' \
--header 'X-Secret-Key: sk_live_your_key'/api/v1/ecommerce/walletcurl --request GET \
--url https://api.paywithstatira.com/api/v1/ecommerce/wallet \
--header 'X-Ecommerce-Key: zec_your_key'E-commerce connections use the same payout request body through their own authenticated endpoint:
/api/v1/ecommerce/payoutscurl --request POST \
--url https://api.paywithstatira.com/api/v1/ecommerce/payouts \
--header 'Content-Type: application/json' \
--header 'X-Ecommerce-Key: zec_your_key' \
--header 'Idempotency-Key: payout_order_84392' \
--data '{
"destinationBankCode": "000013",
"destinationBankName": "GTBank",
"destinationAccountName": "Ada Okafor",
"destinationAccountNumber": "0123456789",
"amountMinor": 250000,
"narration": "Vendor settlement"
}'Send funds to another Statira merchant
Transfers are free, immediate on success, and available through the dashboard or your server-side application. Both merchants must be active and approved, and both wallets must use the same currency.
Save data.walletId from GET /api/v1/gateway/wallet with the merchant and environment. The existing data.id remains the same identifier. A Statira wallet ID is different from a bank account number.
/api/v1/gateway/wallet/transfers/recipient/{walletId}Returns walletId, businessName and currencyCode. Requires wallet.payout.
/api/v1/gateway/wallet/transfersRequires wallet.payout and Idempotency-Key. Supply recipientWalletId, amountMinor and optional narration (maximum 140 characters).
/api/v1/gateway/wallet/transfers/{reference}Requires wallet.view. Only the sending or receiving merchant can retrieve a receipt.
Authenticate with both X-Public-Key and X-Secret-Key from an IP-whitelisted server. These gateway routes do not accept an e-commerce connection key or dashboard bearer token.
/api/v1/gateway/wallet/transfers{
"recipientWalletId": "33333333-3333-4333-8333-333333333333",
"amountMinor": 50000,
"narration": "Invoice 123"
}For NGN, 50000 means ₦500.00. Confirm the recipient name before sending. HTTP 200 returns a SUCCESS receipt containing reference, senderWalletId, recipientWalletId, amountMinor, currencyCode and narration inside data.
- Persist the request and Idempotency-Key before sending. After a timeout, retry the identical request with the same key.
- The same key returns the original receipt. Changed details return HTTP 409.
- Self-transfers, insufficient funds, and mismatched currencies are rejected.
- No wallet-transfer webhook or automatic reversal is provided in this version. Confirm using the response or verification endpoint.
X-Ecommerce-Key with /api/v1/ecommerce/wallet/transfers, /recipient/{walletId}, and /{reference}. Payloads, permissions, and idempotency rules are identical to the gateway routes.Download the developer integration guide · Download the OpenAPI contract for Postman
Core gateway endpoints
/api/v1/gateway/fees/quoteQuote collection or payout fees before confirmation.
/api/v1/ecommerce/fees/quoteQuote fees using an e-commerce key.
/api/v1/gateway/payouts/banksList supported beneficiary bank codes.
/api/v1/gateway/payouts/accounts/verifyVerify the beneficiary account name.
/api/v1/gateway/payouts/{payoutReference}Read payout status.
/api/v1/gateway/payouts/by-idempotency-key/{idempotencyKey}Recover a payout reference after a timeout.
/api/v1/gateway/payments/intentsCreate a payment intent and hosted checkout session.
/api/v1/gateway/payments/intents/{intentReference}/payAuthenticate and initiate a rail to generate bank-transfer instructions.
/api/v1/gateway/payments/verify/{reference}Retrieve the latest verified transaction state.
/api/v1/gateway/payoutsTransfer funds from the authenticated merchant wallet.
/api/v1/gateway/walletRead wallet balances using public and secret keys.
/api/v1/ecommerce/payments/intentsCreate hosted checkout using an e-commerce key.
/api/v1/ecommerce/payments/verify/{reference}Verify a checkout transaction using its TXN reference.
/api/v1/ecommerce/walletRead wallet balances using an e-commerce key.
/api/v1/ecommerce/payoutsCreate a payout using an e-commerce key.
Bank directory lookup and account verification require bank.verify for both gateway and e-commerce keys. This permission cannot send payouts or wallet transfers. All existing merchant API keys receive verification access once during rollout; for a verification-only integration, grant bank.verify and remove wallet.payout. Gateway permissions are assigned per key: payment.create, payment.verify, wallet.view, and wallet.payout. Use TEST keys to test your integration and LIVE keys to accept real payments.
Handle errors predictably
Log the response's correlation identifier when contacting support. Retry temporary failures with exponential backoff and reuse the same idempotency key.
Developer support
Need help with an integration?
Tell us what you're building and include the request correlation ID where available.
support@zijela.com