ZainCash Merchant Payment Gateway – Integration Guide

Thank you for choosing ZainCash, Iraq’s leading mobile payment network. The ZainCash Merchant Payment Gateway provides a secure, scalable, and seamless way for businesses to accept digital payments. By integrating our solution, you offer your customers a fast and familiar checkout experience directly through their mobile wallets.

Version

1.0

Updated

22 Jan, 2026

Overview

The ZainCash Payment Gateway v2 lets you accept payments from ZainCash wallets using a secure redirect flow, with real-time status updates via API and webhooks.

Base URL

https://pg-api-uat.zaincash.iq

Payment Flow

A typical payment using the Payment Gateway v2 looks like this:

  1. Customer starts payment on your website or mobile app.
  2. Your backend authenticates with ZainCash using POST /oauth2/token.
  3. You create a transaction using POST /api/v2/payment-gateway/transaction/init.
  4. You redirect the customer to the Payment Gateway redirectUrl.
  5. Customer completes the payment (including OTP).
  6. ZainCash redirects the customer back to your successUrl or failureUrl with a JWT token.
  7. Your backend verifies the JWT and/or calls the Inquiry API to confirm final status.
  8. Optionally, you receive webhook notifications for status changes and refunds.

For most merchants, the source of truth should be the webhook event. Use the redirect token for UX and the inquiry endpoint as a fallback.

Environments

  • Test: https://pg-api-uat.zaincash.iq
  • Production: Provided during onboarding.

Use separate client credentials per environment.

High-level capabilities

  • Wallet.
  • OTP-based authentication where applicable.
  • Inquiry and reversal APIs.
  • JWT-based redirect and webhook callbacks.

Quickstart

This is the fastest way to go from zero to a working payment:

  1. Obtain your client_id, client_secret, and API key from ZainCash.
  2. Get an OAuth2 access token using client_credentials grant.
  3. Call the transaction/init endpoint to create a payment.
  4. Redirect the user to redirectUrl from the response.
  5. Handle the redirect to your successUrl/failureUrl using the token.
  6. Verify the JWT and update your order status.

1. Get Access Token

POST

/oauth2/token

2. Create Payment

POST

/api/v2/payment-gateway/transaction/init

Use a unique externalReferenceId each logical payment attempt. This acts as an idempotency key and helps you reconcile payments on your side.

Authentication

All API requests (except /oauth2/token) require a valid bearer token in the Authorization header.

Endpoint

POST

/oauth2/token

Header

Value

Content-Typeapplication/x-www-form-urlencoded

Body Parameters

Field

Type

Required

Description

grant_typestringyesMust be client_credentials.
client_idstringyesYour client ID.
client_secretstringyesYour client secret.
scopestringyesSpace-separated scopes, e.g., payment:read payment:write.

Get Access Token

Response

Use the access token in all subsequent API requests.

Create Payment

Create a new payment session and obtain the redirectUrl where you should send the customer to complete the payment.

POST

/api/v2/payment-gateway/transaction/init

Scopes

payment:read

Header

Value

AuthorizationBearer <access_token>
Content-Typeapplication/json

Field

Type

Required

Description

languagestringyesPlease make sure to choose the correct language based on your application locale. Supported values: "En" for English, "Ar" for Arabic And "Ku" for Kurdish.
externalReferenceIdstring (UUID)yesUnique per request; use for idempotency and reconciliation.
orderIdstringyesYour internal order identifier.
serviceTypestringyesService identifier (e.g., JAWS) provided by ZainCash.
amount.valuestring / numberyesTransaction amount.
amount.currencystringyesMust be IQD.
customer.phonestringoptionalCustomer phone in international format (e.g., 96477...).
redirectUrls.successUrlstringyesWhere the user is redirected after a successful payment.
redirectUrls.failureUrlstringyesWhere the user is redirected after a failure or cancel.

Create Payment

Request Body

Sample Response

Always redirect the customer to the returned redirectUrl. Do not attempt to construct this URL manually.

Transaction Inquiry

Retrieve the latest status and details for a given payment transaction.

GET

/api/v2/payment-gateway/transaction/inquiry/{transactionId}

Scopes

payment:read

Parameter

Location

Type

Required

Description

transactionIdPathstring (UUID)yesTransaction ID from the init response.

Transaction Inquiry Request

Sample Response

Status Values

SUCCESS

FAILED

PENDING

OTP_SENT

CUSTOMER_AUTHENTICATION_REQUIRED

EXPIRED

REFUNDED

Reverse

Reverse a successfully completed transaction.

POST

/api/v2/payment-gateway/transaction/reverse

Scopes

reverse:write

Reverse/Refund Request

Request Body

Field

Type

Required

Description

transactionIdstring (UUID)yesThe original successful transaction ID.
reasonstringyesBusiness reason for initiating the reversal.

Sample Response

Redirect Callback

After the customer completes payment on the Payment Gateway page, ZainCash redirects the user back to your site.

Redirect URLs:

  • successUrl?token=JWT_TOKEN
  • failureUrl?token=JWT_TOKEN

Decoded Token Example

Verify the JWT signature using your API key and HS256 algorithm . Never trust callback data without verifying the token integrity .

Webhooks

Webhooks allow ZainCash to notify your backend whenever a transaction status changes or a refund completes. You configure a server-side notificationUrl that receives POST requests.

Prerequisites:

  • Contact the business team to set the webhook URL in our system and register it.
  • Please ensure that the webhook URL is separate from the success and failure URLs.
  • The configuration of the webhook only works in production and doesn't work in the test environment

Create WebHook

Webhook Request

Method

Header

Description

POSTContent-Type: application/jsonBody contains a webhook_token (JWT string).

Decoded JWT Example STATUS_CHANGED SUCCESS

Decoded JWT Example STATUS_CHANGED FAILED

Webhook Testing with cURL

Use eventId for idempotency. If you receive the same eventId more than once, process it only once and return HTTP 200.

The configuration of the webhook only works in production and doesn’t work in this test environment.

The webhook payload gets sent by us only after the user finishes the last step in the payment and will be sent even if it’s a success or a failure you can check the body for it

Status & Params

Here are all the params that you need to know about the response and request:

Params

Field

Type

Required

Description

Location

grant_typestringyesMust be client_credentials./oauth2/token endpoint body request
client_idstringyesYour client ID./oauth2/token endpoint body request
client_secretstringyesYour client secret./oauth2/token endpoint body request
scopestringyesSpace-separated scopes, e.g., payment:read payment:write./oauth2/token endpoint body request
languagestringyesLanguage code: En, Ar, or Ku./api/v2/payment-gateway/transaction/init endpoint body request
externalReferenceIdstring (UUID)yesUnique per request; use for idempotency and reconciliation./api/v2/payment-gateway/transaction/init endpoint body request
orderIdstringyesYour internal order identifier./api/v2/payment-gateway/transaction/init endpoint body request
serviceTypestringyesService identifier (e.g., JAWS) provided by ZainCash./api/v2/payment-gateway/transaction/init endpoint body request
amount.valuestring / numberyesTransaction amount./api/v2/payment-gateway/transaction/init endpoint body request
amount.currencystringyesMust be IQD./api/v2/payment-gateway/transaction/init endpoint body request
customer.phonestringoptionalCustomer phone in international format (e.g., 96477...)./api/v2/payment-gateway/transaction/init endpoint body request
redirectUrls.successUrlstringyesWhere the user is redirected after a successful payment./api/v2/payment-gateway/transaction/init endpoint body request
redirectUrls.failureUrlstringyesWhere the user is redirected after a failure or cancel./api/v2/payment-gateway/transaction/init endpoint body request
transactionIdstring (UUID)yesTransaction ID from the init response./api/v2/payment-gateway/transaction/inquiry/{transactionId} endpint body request
transactionIdstring (UUID)yesThe original successful transaction ID./api/v2/payment-gateway/transaction/reverse endpont response body
reasonstringyesBusiness reason for initiating the reversal./api/v2/payment-gateway/transaction/reverse endpont response body

Status

Status Code

Description

SUCCESSThe final states of the transaction lifecycle . after a successful payment.
FAILEDThe final states of the transaction lifecycle . after a failed payment attempt.
PENDINGTransaction created; awaiting next steps.
OTP_SENTOTP delivered to the customer for authentication.
CUSTOMER_AUTHENTICATION_REQUIREDExtra steps required (e.g., phone validation/fee computation pending or failed)
EXPIREDTransaction exceeded its expiry time.
REFUNDEDThe final states of the transaction lifecycle after a successful reversal/refund.
STATUS_CHANGEDEmitted when a transaction’s status after the payment process ends..
REFUND_COMPLETEDEmitted when a reversal/refund succeeds.
REFUND_FAILEDEmitted when a reversal fails.

Scopes

Scopes are basically the permissions needed for authorization to use the endpoints.

Scope

Description

payment:readFor writing privileges for payment gateway transaction processing
payment:writeFor reading privileges for payment gateway transaction processing
reverse:writeFor reversing a transaction

Status & Error Handling

Common error patterns you may encounter when integrating.

HTTP Status Codes

HTTP Code

Description

Notes

400Bad RequestInvalid format (e.g., non-UUID transactionId) or missing fields.
401UnauthorizedMissing / invalid bearer token, or expired token.
403ForbiddenTransaction not owned by this merchant (e.g., PAYMENT_GATEWAY_UNAUTHORIZED).
404Not FoundTransaction does not exist (PAYMENT_GATEWAY_TRANSACTION_NOT_FOUND).

Recommendations

  • Always log the HTTP status, error code, and full response body.
  • Use a correlation ID if provided by the gateway for debugging with ZainCash support.

Best Practices

Integration Guidelines

Idempotency

  • Use a unique externalReferenceId per payment attempt.
  • Do not reuse the same ID for multiple different orders.
  • On duplicate errors, perform an inquiry to determine the current status.

Security

  • Never expose your client_secret or API key in client-side code.
  • Verify all JWT tokens (redirect and webhook) using your API key and HS256.
  • Use HTTPS for all your redirect and notification URLs.

Resilience

  • Prefer webhooks as the primary signal for final status.
  • Use transactional retries with backoff when calling the gateway APIs.
  • Implement fallbacks with the inquiry API if webhooks are delayed.

Customer Wallet Management

The customer.phone field in the /transaction/init request is optional. ZainCash recommends the following approach for populating it.

Recommended flow

1. First-time payment — omit customer.phone

For a customer's first "Pay with ZainCash" transaction on your platform, send the /transaction/init request without the customer.phone field. ZainCash will prompt the customer to enter their wallet mobile number manually on the payment page.

2. Capture the wallet number from the success callback

Once the payment is completed successfully, ZainCash redirects the customer to your successUrl with a signed JWT token. After verifying the token with your API Secret Key, extract the payer wallet number from the token payload and store it against the customer's profile in your system.

3. Keep the stored wallet number up to date

After every successful transaction, update the stored wallet number with the new wallet number used in that transaction. Always rely on the Wallet Number from the latest successful payment — not only the first one — since a customer may switch wallets over time.

4. Subsequent payments — pass the latest saved wallet number

For every following transaction by the same customer, include the most recently saved wallet number in the customer.phone field of the /transaction/init request. The customer will not need to re-enter their wallet number on the payment page.

Use the wallet number captured from the latest successful ZainCash transaction rather than the mobile number registered on your platform, since the two may not be the same.

Brand Guidelines

Why this guideline:

  • To ensure consistent, professional, and user-friendly integration of “Pay with ZainCash” across web and mobile platforms.
  • To help merchants, developers, and designers implement ZainCash payment with correct branding, UI behavior, and user flow.
  • To maintain the integrity of ZainCash’s visual and interaction identity across partners.

Who should use this:

  • Front-end developers / integration engineers implementing ZainCash Pay.
  • UI/UX designers building checkout flows with ZainCash.
  • Product/marketing teams referencing ZainCash in UI, marketing, or payment-option contexts.

Brand Identity: Name, Logo & Visual Elements

Brand Name & Terminology:

  • Always refer to the service as “ZainCash” or “ZainCash Pay”. Do not abbreviate, translate, or alter the name (e.g., avoid “Z-Pay”, “ZCash wallet”, etc.).
  • In user-facing text, use consistent capitalization: capital “Z” and “C” — e.g., “Pay with ZainCash”.
  • The merchant must ensure that the correct language is used based on the customer’s language on the merchant platform. Supported languages are Arabic, English, and Kurdish.

Logo / Mark Usage:

  • Use only the official ZainCash logo or brand mark provided in their “Branding Guideline” asset pack.
  • Do not recolor, distort, stretch, or apply shadows or extra effects to the logo.
  • Maintain sufficient clear-space around the logo (no overlapping with other UI elements).
  • Do not combine the logo with other symbols or custom icons in a way that alters its appearance.

Buttons

Button Style

  • Provide a dedicated button or UI element labeled “Pay with ZainCash” (or similar), when showing payment options.
  • Button styling should be clean, contrasting, and legible — consistent in padding, size, and color across pages (checkout, product page, etc.).
  • On light backgrounds — use a version of button that ensures text/logo readability; on dark or complex backgrounds — ensure contrast (e.g. light text/logo on dark background)
  • The button must trigger the actual ZainCash payment flow (not just a UI placeholder).

Primary Button

Button

Primary Button Disabled

Button

Secondary Button

Button

Secondary Button Disabled

Button

Button Sizing Guidelines

1. Minimum Button Size (Smallest Allowed)

  • To ensure readability + tapability (especially on mobile):

Minimum button size:

  • Width: 120px
  • Height:40px

Padding (Minimum):

  • Horizontal padding:16px
  • vertical padding:8–12px

Minimum Button Size:

2. Recommended Standard Button Size

  • This is the size most platforms use for wallet payments:

Standard recommended size:

  • Width: 200–240px
  • Height:48-54px

Padding (Recommended)

  • Horizontal padding:20-24px
  • vertical padding:12-14px

Standard Button Size

3. Largest Button Size (Maximum Recommended)

  • Avoid going too large — keep it balanced and professional.

Largest size:

  • Width:300–320px
  • Height:56–64px

Padding (Recommended)

  • Horizontal padding:24–32px
  • vertical padding:14-16px

Largest Button Size

Test Credentials

Test credentials used to make tests in a safe environment to try and handle all possible responses before going live.

Merchant

Please use the following merchant credentials to test transaction ID creation and status checks. Ensure you copy the credentials exactly as shown, without spaces, and note that the secret key must be entered as a single line.

#

MSISDN

Client ID

Client Secret

19647829744545

758055f4a8044779a35f6ceb69f858b3

bibLCGTxVAig5To3OLLKPJQMlRR7Pefp

Customer

Please select one of the following customer test wallets to submit your transaction.

#

MSISDN

PIN

OTP

196478029995691111111111
296478297444321111111111
396478297444641111111111
496478297444741111111111

Going Live

Finished testing? Congratulations! You are ready to move to the live environment.

If you have already submitted your business request: Please contact your Business Development Account Manager to obtain your live credentials.

If you haven’t submitted a request yet, please complete your application by clicking here.

Merchant Dashboard

Once your business is registered in the ZainCash system, you will gain full access to our powerful reporting portal.

  1. 1- Check Your Email: You will automatically receive your login credentials from [email protected].

  2. 2- Log In: Access the Merchant Dashboard using your provided Merchant Password.

  3. 3- Take Control: Search transactions, view real-time history, and process reversals or partial refunds with one click.

FAQ

Didn’t find what you’re looking for?

Support

If you require any support or have questions not covered in this documentation, please open a request through our Ticket System.

Our team is available Sunday through Thursday, from 9:00 AM to 5:00 PM (Baghdad Time). We strive to respond to all inquiries within 12–24 hours on business days. While response times may occasionally be extended during peak periods, we are committed to providing you with a resolution as quickly as possible.

Please refer to the Service Level Agreement (SLA) table below for detailed response times related to Production issues only:

Severity Level

Definition

Response Time

Resolution Time

P1 HighComplete Outage (Payment Gateway API down). Major degradation impacting a large portion of payments, but not a total outage. Merchant dashboard down, cash disbursement.<1 Hour<8 Hours
P2 MediumLimited disruption affecting a subset of transactions or non-financial functions (e.g., merchant dashboard reports not updating real-time, no financial loss).<4 Hours<24 Hours
P3 LowMinor/localized issues with no significant business or financial impact (e.g., single refund delayed, individual user cases) or settlement delayed by 1 day.<1 Business Day<10 Business Days

Note: While we aim to provide the best support possible, please keep in mind that it only extends to resolving technical matters. We will not implement the integration for you or fix unrelated issues. However, we will suggest fixes and provide guidance.