Skip to content

Top-ups ​

Create a Taura top-up for a phone number and read the result from the returned status.

Top-up statuses ​

StatusWhat your integration should do
pendingWait and check the top-up again before updating the customer order. Repeating the same ref returns this top-up and does not send it again.
completedMark the customer order as successful.
failedRead failure_reason. Use a new ref only if the customer wants another attempt.
under_reviewDo not submit a duplicate. Keep the uuid and ref, and contact Xash support if needed.

Top-up fields ​

FieldTypeNotes
uuidstringTaura Xashpay top-up identifier.
refstringYour reference for the customer request.
recipientstringRecipient phone number.
unitsnumberTop-up amount in UNITS.
statusstringpending, completed, failed, or under_review.
wallet_transaction_uuidstring|nullRelated wallet transaction identifier.
vendor_referencestring|nullCompletion reference when available.
failure_reasonstring|nullReason supplied for an unsuccessful or reviewed top-up.
created_atstring|nullISO 8601 timestamp.

POST/api/v1/taura/topups ​

Create a top-up.

Request body ​

FieldTypeRequiredNotes
recipientstringYesPhone number in E.164 format, such as +263775696233. Maximum 16 characters.
unitsnumberYesPositive amount in UNITS.
refstringYesYour unique reference. Maximum 120 characters.

Use the same ref for the same request ​

If you retry the same customer request, send the same ref. The API returns the existing top-up instead of creating another one. Use a new ref only for a new customer request.

Example request ​

bash
curl --request POST "https://taura.xashpay.com/api/v1/taura/topups" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer TOKEN" \
  --data '{
    "recipient": "+263775696233",
    "units": 25.00,
    "ref": "ORDER-10045"
  }'

Response: 201 ​

json
{
  "topup": {
    "uuid": "2236170a-85fb-4354-ab0b-941871ecfab0",
    "ref": "ORDER-10045",
    "recipient": "+263775696233",
    "units": 25.0,
    "status": "completed",
    "wallet_transaction_uuid": "9cbce09d-0d13-4cad-a7aa-537f51f5ef23",
    "vendor_reference": "TXN-10045",
    "failure_reason": null,
    "created_at": "2026-08-31T08:20:00+00:00"
  }
}

Always branch on status. Do not treat HTTP 201 alone as confirmation that the top-up completed.

Request errors ​

  • HTTP 422 means a request field is invalid or the wallet balance cannot cover the amount.
  • HTTP 429 means the rate limit was reached. Wait for Retry-After, then retry with the same ref.

See Errors for the response format.

GET/api/v1/taura/topups ​

List your top-ups, newest first.

Query parameters ​

ParameterTypeRequiredNotes
per_pageintegerNoDefault 20.
pageintegerNoPage number, starting at 1.

Example request ​

bash
curl "https://taura.xashpay.com/api/v1/taura/topups?per_page=20" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer TOKEN"

The response contains a topups array. Each item uses the fields listed in Top-up fields. Request the next page with ?page=2. An empty array means that page has no records.

GET/api/v1/taura/topups/lookup ​

Look up one of your top-ups by the ref you sent when you created it. This endpoint only reads. It never sends a top-up, retries one, or changes your wallet.

Query parameters ​

ParameterTypeRequiredNotes
refstringYesThe ref of the top-up. Maximum 120 characters.
include_balancestringNotrue or 1 adds the recipient's account check. false, 0 or leaving it out keeps the response below.
include_retry_authorizationstringNotrue or 1 adds the top-up's latest retry authorization.

Example request ​

bash
curl --get "https://taura.xashpay.com/api/v1/taura/topups/lookup" \
  --data-urlencode "ref=ORDER-10045" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer TOKEN"

Response: 200 ​

json
{
  "topup": {
    "uuid": "2236170a-85fb-4354-ab0b-941871ecfab0",
    "ref": "ORDER-10045",
    "recipient": "+263775696233",
    "units": "25.00000000",
    "status": "completed",
    "vendor_reference": "TXN-10045",
    "failure_reason": null,
    "created_at": "2026-08-31T08:20:00+00:00",
    "completed_at": null
  }
}

The fields match Top-up fields, with these differences:

  • units is a string with exactly 8 decimal places, the precision stored for the top-up. For example, "0.19230760" or "25.00000000". It is not rounded to 2 decimal places as it is in the other top-up responses, so you can compare it with the amount you sent.
  • wallet_transaction_uuid is not included.
  • completed_at is added. It is always null for now because completion times are not recorded yet.

If you have no top-up with that ref, the response is still HTTP 200:

json
{
  "topup": null
}

null means no record is stored for that ref. It does not prove that no recharge was sent, and neither does status: failed. Contact Xash support before sending the same request again under a new ref.

Recipient account check ​

Send include_balance=true to get the recipient's Taura account and balance next to the top-up. The recipient always comes from the stored top-up, never from the request. Nothing is sent, retried, settled or refunded.

bash
curl --get "https://taura.xashpay.com/api/v1/taura/topups/lookup" \
  --data-urlencode "ref=ORDER-10045" \
  --data-urlencode "include_balance=true" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer TOKEN"
json
{
  "topup": {
    "uuid": "2236170a-85fb-4354-ab0b-941871ecfab0",
    "ref": "ORDER-10045",
    "recipient": "+263775696233",
    "units": "25.00000000",
    "status": "under_review",
    "vendor_reference": null,
    "failure_reason": "Deadline Exceeded",
    "created_at": "2026-08-31T08:20:00+00:00",
    "completed_at": null
  },
  "account_check": {
    "outcome": "exists",
    "recipient": "+263775696233",
    "monetary_balance": "1.65",
    "monetary_balance_unit": "$",
    "currency": null,
    "voice_balance": "0.00",
    "voice_balance_unit": "minutes",
    "checked_at": "2026-08-31T09:02:11+00:00",
    "freshness": "fresh",
    "failure_code": null
  }
}
FieldTypeNotes
outcomestringexists: Taura recognised the account. not_found: Taura reported no such account. unavailable: no answer could be read.
recipientstringThe top-up's recipient.
monetary_balancestring|nullBalance as Taura prints it, for example "1.65". null unless outcome is exists.
monetary_balance_unitstring|nullThe symbol Taura prints before the balance, currently "$".
currencystring|nullISO currency code once Taura confirms one. Always null for now: the $ symbol is not proof of a currency.
voice_balancestring|nullVoice balance, for example "0.00". null unless outcome is exists.
voice_balance_unitstring|null"minutes" when voice_balance is set.
checked_atstring|nullISO 8601 time Taura was asked. null when no lookup was made.
freshnessstringfresh: looked up for this request. cached: a check of this top-up from the last 60 seconds is returned instead. none: no lookup was made (see failure_code).
failure_codestring|nullWhy there is no balance: timeout, rate_limited, unauthorized, server_error, http_error, request_failed, malformed_response, missing_balance, unrecognised_response, account_not_found, lookup_rate_limited (your balance-check limit) or lookup_busy (Taura's shared limit).

If the account check fails or times out, the response is still HTTP 200 with the full topup, and account_check has outcome: "unavailable" and null balances:

json
{
  "topup": { "ref": "ORDER-10045", "status": "under_review", "...": "..." },
  "account_check": {
    "outcome": "unavailable",
    "recipient": "+263775696233",
    "monetary_balance": null,
    "monetary_balance_unit": null,
    "currency": null,
    "voice_balance": null,
    "voice_balance_unit": null,
    "checked_at": "2026-08-31T09:02:19+00:00",
    "freshness": "fresh",
    "failure_code": "timeout"
  }
}

A null balance never means zero. A real zero balance is "0.00" with outcome: "exists".

A balance is not proof of delivery

A zero balance can follow spending, and a positive balance can come from another recharge. Do not decide that an earlier top-up did or did not deliver from the balance alone.

Balance checks have their own limit of 30 per minute per vendor, inside the lookup limit. Over it, the top-up is still returned and account_check has failure_code: "lookup_rate_limited". Each check is recorded against the top-up.

Retry authorization ​

An under-review top-up has an unknown delivery outcome, so it is never sent again automatically. A Taura Xashpay admin can allow one more send, either after Taura confirms the earlier attempt was not delivered, or by accepting that the recipient may receive the units twice. Send include_retry_authorization=true to see that permission:

json
{
  "topup": { "ref": "ORDER-10045", "status": "under_review", "...": "..." },
  "retry_authorization": {
    "id": "8f0f3f8e-5a2b-4d5b-9a55-0f6c1c2d7e10",
    "decision": "duplicate_risk_accepted",
    "status": "active",
    "ref": "ORDER-10045",
    "recipient": "+263775696233",
    "units": "25.00000000",
    "uncertain_attempt": 1,
    "granted_after_attempt": 1,
    "current_send_attempt": 1,
    "granted_at": "2026-08-31T10:15:00+00:00",
    "consumed_at": null,
    "consumed_send_attempt": null,
    "voided_at": null,
    "send_queued": false
  }
}

retry_authorization is null when none was ever granted.

FieldTypeNotes
idstringName this in retry_authorization when you retry.
decisionstringconfirmed_not_delivered: Taura confirmed the uncertain attempt was not delivered. duplicate_risk_accepted: the earlier attempt may have delivered and a second delivery was accepted. These are different decisions; do not treat one as the other.
statusstringactive: one retry naming id may send. consumed: a retry already used it. void: the top-up changed (an outcome, another attempt or a decision) and it no longer applies.
ref, recipient, unitsstringExactly what it covers. Only act on it if all three match your record.
uncertain_attemptinteger|nullThe send attempt whose outcome was unknown when it was granted.
granted_after_attemptintegerThe latest send attempt when it was granted. The retry it allows is the next one.
current_send_attemptintegerThe top-up's latest send attempt now.
consumed_at, consumed_send_attemptstring|null, integer|nullWhen and as which attempt it was used.
send_queuedbooleanAlways false. Taura Xashpay only grants permission; it never queues or sends the retry for you.

To use an active authorization, call the retry-only endpoint POST /api/v1/taura/topups/retry with the original details and name it. The retry still checks the recipient's account first and sends nothing if the check fails; the authorization then stays active for your next retry. It is used by the first retry that sends, and a second retry naming it is refused with retry_blocked: "retry_authorization_invalid":

json
{
  "recipient": "+263775696233",
  "units": 25,
  "ref": "ORDER-10045",
  "retry_authorization": "8f0f3f8e-5a2b-4d5b-9a55-0f6c1c2d7e10"
}

If that retry's outcome is unknown again, the top-up is blocked again and needs a new decision.

Request errors ​

  • HTTP 422 means ref is missing, blank, or longer than 120 characters, or an include_ option is not true, false, 1 or 0.
  • HTTP 429 means the lookup rate limit was reached. Wait for Retry-After, then try again.

Taura Xashpay vendor API documentation. Contact Xash support for access.