Verify and charge
Checks the code and, if the anti-fraud verdict allows, charges the subscriber once.
POST /api/sp/v1/dcb/purchase/verify
Request
| Field | Type | Notes |
|---|---|---|
msisdn | string | The subscriber's number. |
shortCode | string | The short code your credential is bound to. |
serviceId | integer | The service. |
spTransactionId | string | Yours, unique per attempt. See Idempotency. |
pin | string | The one-time code the subscriber typed. |
ti | string | The anti-fraud transaction identifier from your script call. |
ts | string | The matching timestamp. |
amount is prohibited here too. The price is the service's, not the request's.
Order of operations
- The code is checked.
- Eligibility is re-checked.
- The anti-fraud verdict is obtained.
- The charge is made.
Nothing is charged until all three checks pass, which is why a refusal at any step leaves the subscriber's balance untouched.
Response
{
"requestId": "01JB2K9WQ4X7YH3M8N5P6R7T8V",
"code": "OK",
"data": {
"purchaseId": "01JB2K9WQ4X7YH3M8N5P6R7T8V",
"amount": 500,
"currency": "IQD",
"chargedAt": "2026-09-13T08:22:40.000000Z"
}
}
| Field | Notes |
|---|---|
purchaseId | Ours. Store it - it is what a refund or a dispute is quoted against. |
amount | What was charged. |
currency | IQD. |
chargedAt | ISO 8601. |
A failed charge returns these same four fields, under data, alongside
INSUFFICIENT_BALANCE or CHARGE_FAILED. So store data on both outcomes and you have one record
per attempt rather than a gap wherever a charge failed. See the envelope.
Creates nothing ongoing
A purchase is a single charge. No subscription is created, nothing renews, and there is nothing to unsubscribe from afterwards.
What can refuse it
The PIN codes, the eligibility codes, the anti-fraud codes, plus CHARGE_FAILED and
INSUFFICIENT_BALANCE: the last two meaning the operator declined the charge itself.
INSUFFICIENT_BALANCE is worth handling distinctly in your UI. It is the one refusal the
subscriber can do something about immediately.