Whish Money
Whish Money
Partner Integration Guide

Direct Credit

Credit funds from your merchant account directly into a customer's Whish wallet. This is a wallet-to-wallet transfer, settled instantly.

REST over HTTPS with JSON requests and responses. Intended for authorized distributors.

v1.0.0Platform: WhishJSON over HTTPSAuthor: TecFrac
Authentication
channel + secret + websiteUrl
Production base URL
https://api.whish.money/itel-service/api
Currencies
USD · LBP

Integration flow

  1. 1
    Credit the wallet. Call Send a whish-to-whish credit with the recipient msisdn, countryCode, amount, currency, and a unique externalId. This endpoint requires IP whitelisting.
  2. 2
    Funds settle instantly. The amount lands in the recipient's Whish wallet immediately; there is no separate settlement step.
  3. 3
    Confirm the outcome. Call Get credit status with the same externalId to verify before you record the payout as complete.
  4. 4
    Retry safely. On a timeout, resend the same externalId; an already-processed credit replays its recorded result and never double-credits.

Authentication & headers

Every request must include the HTTP headers below, plus Content-Type: application/json on requests that send a body.

HeaderDescription
channelValue provided by Whish.
secretValue provided by Whish.
websiteUrlSite URL or app name. Use the exact value Whish issued with your keys.
User-AgentIdentifies your app. Use your own details, not Whish's. Format: AppName/version (website; contact-email). Example: AcmeStore/2.1 (https://acme.example; dev@acme.example).

Keep your credentials secret. They authorize account actions and money movement, so send them only over HTTPS, store them in a secure secrets manager, and never expose them in client-side code, logs, or version control. Rotate them immediately if you suspect a leak.

Environments

EnvironmentBase URLPurpose
Sandboxhttps://partner.api.sbx.whish.money/itel-service/apiTesting, QA, integration verification.
Productionhttps://api.whish.money/itel-service/apiLive environment for real transactions.

The cURL examples on this page target Sandbox. To go live, swap the host for the Production base URL above.

Response format

All endpoints return HTTP 200 with Content-Type: application/json and a shared envelope. Always branch on the status and code fields in the body, never on the HTTP status code.

FieldTypeDescription
statusBooleantrue when the call was accepted and processed. false when it was not; read code for the reason.
codeStringnull whenever status is true. When status is false, an operation-specific error code; the value 500 is special (see below). This field only ever reports errors, never a transaction's progress.
dialogObjectOptional title / message to display to the user.
dataObjectResponse payload for the operation; shape varies per endpoint (and may be a scalar or null for some operations).
actions / extraObjectReserved; typically null.
retrievedBooleanPresent on idempotent operations. true means this response replays an already-processed request (the original was not run again); false or absent means it ran now.

The two fields move together, so read them as a pair. There are only these combinations:

statuscodeTreat as
truenullSucceeded. Process data.
false500Pending. The call did not return an outcome, so the result is unknown rather than failed. Reconcile as described below; do not mark it failed.
falseany other codeFailed, unless that code is a documented challenge for the endpoint you called (for example a required provider OTP). Handle documented challenges as an expected step in the flow, not as a failure; see the relevant endpoint reference.

A status: true is never accompanied by a code, and a code never reports how far a transaction has progressed. Where an operation has a lifecycle of its own (created, paid, refunded), the endpoint reports it on a separate field inside data; see that endpoint's response fields.

Get account balance

Returns the real balance of the account for the given currency. Pass currency as a query-string parameter on the request URL.

GET/payment/account/balance?currency={currency}
ParameterTypeRequiredDescription
currencyStringRequiredCurrency to return the balance for: USD or LBP. Sent in the query string, for example ?currency=USD.

Each channel supports two currencies (USD and LBP). Use currency to pick which balance to return.

Example request · cURL
cURL · Sandbox
curl 'https://partner.api.sbx.whish.money/itel-service/api/payment/account/balance?currency=USD' \
  -H 'channel: YOUR_CHANNEL' \
  -H 'secret: YOUR_SECRET' \
  -H 'websiteUrl: https://yoursite.com' \
  -H 'User-Agent: AcmeStore/2.1 (https://acme.example; dev@acme.example)'
Response · 200 success
application/json
{
  "status": true,
  "code": null,
  "dialog": null,
  "actions": null,
  "extra": null,
  "data": {
    "balance": 940977.0
  }
}

Send a whish-to-whish credit

Sends a wallet-to-wallet (W2W) transfer from the merchant account to a customer's Whish wallet.

Requires IP whitelisting. The sendw2w endpoint only accepts requests from source IPs that Whish has registered for your account. Provide Whish with the public egress IP(s) your servers call from (Sandbox and Production) to be allowlisted; otherwise requests are rejected. See IP whitelisting.

POST/payment/sendw2w
Example request · cURL
cURL · Sandbox
curl -X POST 'https://partner.api.sbx.whish.money/itel-service/api/payment/sendw2w' \
  -H 'channel: YOUR_CHANNEL' \
  -H 'secret: YOUR_SECRET' \
  -H 'websiteUrl: https://yoursite.com' \
  -H 'User-Agent: AcmeStore/2.1 (https://acme.example; dev@acme.example)' \
  -H 'Content-Type: application/json' \
  -d '{
  "externalId": "1234",
  "note": "Payout for order #A-1234",
  "countryCode": "961",
  "msisdn": "+9617XXXXXXX",
  "amount": 50.0,
  "currency": "USD"
}'

Request body

FieldTypeRequiredDescription
externalIdStringRequiredUnique per transaction (idempotency key).
noteStringOptionalPayment reason or internal remark.
countryCodeStringRequiredRecipient's international dialing code (e.g. 961).
msisdnStringRequiredRecipient wallet number, starting with + and country code (e.g. +961XXXXXXXX).
amountDoubleRequiredAmount to transfer.
currencyStringRequiredCurrency: USD or LBP.
Request
Request body
{
  "externalId": "1234",
  "note": "Payout for order #A-1234",
  "countryCode": "961",
  "msisdn": "+9617XXXXXXX",
  "amount": 50.0,
  "currency": "USD"
}
Response · 200 success
application/json
{
  "status": true,
  "code": null,
  "dialog": null,
  "actions": null,
  "extra": null,
  "data": null
}

Get credit status

Returns the status of a W2W transaction. Pass externalId and currency as query-string parameters on the request URL. Read the outcome from the shared envelope, exactly as described in Response format: status: true means the credit was found and completed, status: false with code: 500 means still pending, and any other code is a definitive failure.

GET/payment/sendw2w/status?externalId={externalId}&currency={currency}
ParameterTypeRequiredDescription
externalIdStringRequiredExternal identifier of the W2W transaction (the same value you sent on the credit). Passed in the query string, for example ?externalId=123456.
currencyStringRequiredTransaction currency: USD or LBP. Sent in the query string, for example &currency=USD.
Example request · cURL
cURL · Sandbox
curl 'https://partner.api.sbx.whish.money/itel-service/api/payment/sendw2w/status?externalId=123456&currency=USD' \
  -H 'channel: YOUR_CHANNEL' \
  -H 'secret: YOUR_SECRET' \
  -H 'websiteUrl: https://yoursite.com' \
  -H 'User-Agent: AcmeStore/2.1 (https://acme.example; dev@acme.example)'
Response · 200 (completed) success
application/json
{
  "status": true,
  "code": null,
  "dialog": null,
  "actions": null,
  "extra": null,
  "retrieved": true,
  "data": null
}
Response · 200 (still pending) failure
application/json
{
  "status": false,
  "code": 500,
  "dialog": null,
  "actions": null,
  "extra": null,
  "retrieved": false,
  "data": null
}

retrieved: true here means the credit was already processed and its recorded result is being returned (not re-run). Use this endpoint to reconcile after a timeout by re-querying the same externalId. A completed credit returns data: null: the outcome is carried by status and code, not by a payload.

IP whitelisting

The Send a whish-to-whish credit (sendw2w) endpoint is IP-restricted: it only accepts requests from source IPs that Whish has registered for your account.

Send Whish the public egress IP address(es) your servers call from, for both Sandbox and Production, and Whish allowlists them on their side. Until your IPs are registered, sendw2w requests are rejected.

This is the you → Whish direction: you register your server IPs with Whish. Direct Credit has no callbacks, so there are no Whish source IPs for you to allowlist here. Keep your egress IPs stable (for example a dedicated NAT gateway) so allowlisting does not break as your infrastructure scales.

Error codes

Every code below is returned with status: false. Match the string exactly and branch on it, never on the dialog message text, which is written for display and can change.

Re-sending an already-used externalId never re-executes the transaction: the recorded result is replayed verbatim, including the original error code (safe retry, no double charge).

Direct Credit codes

CodeMeaningRecommended handling
bill.invalid_amount_message_minAmount is zero, negative, or below the service minimum.Send a valid amount.
auth.wrong_phone_formatRecipient msisdn cannot be parsed or validated.Fix the msisdn (E.164 for the target country).
auth.wrong_country_codeThe msisdn's country does not match the countryCode field.Align countryCode with the msisdn.
invalid_currencyUnsupported currency.Send a supported currency.
p2p.receiver_same_as_senderSender and recipient are the same account.Use a different recipient.
p2p.cannot_receiveRecipient account is inactive or deleted.Recipient must contact Whish; final failure.
topup.cannot_receiveRecipient's account type or tags do not allow receiving W2W transfers.Final failure for this recipient.
auth.restricted_countryRecipient's country is not enabled for this service.Final failure for this destination.
p2p.note.too.longThe note exceeds the configured maximum length.Shorten the note.
p2p.limit_reached / p2p.limit_reached_countDaily W2W amount or count limit reached.Wait until next day or request a limit increase.
p2p.monthly_limit_reached_amount / p2p.monthly_limit_reached_count / p2p.Monthly_limit_reachedMonthly W2W amount or count limit reached (variant depends on account tier).Wait until next month, request an increase, or complete eKYC.
transfer.failed.titleRecipient would exceed their maximum wallet balance.Recipient must reduce balance or upgrade verification.
refresh.denominationsDirect-credit service is not configured server-side.Contact Whish.
itel.unknown_errorServer misconfiguration or unhandled error.Escalate to Whish if persistent.

Common codes (all payment & billing endpoints)

Authentication, session, and request validation:

CodeMeaningRecommended handling
auth.session_not_existMissing or invalid session token.Re-authenticate, then retry.
auth.session_expiredSession token expired.Re-authenticate, then retry.
400Required parameters or headers are missing, or the body failed field-level validation.Fix the request payload; do not retry unchanged.
timestamp.invalidRequest timestamp is outside the allowed clock-skew window.Sync the client clock (NTP), then retry.
request.invalid / device.invalid_osDevice or channel-level validation rejected the request.Verify your integration headers; contact Whish if persistent.
500Unhandled server-side exception.Retry with backoff using the same externalId to avoid double execution; report if persistent.
itel.unknown_errorGeneric fallback for unexpected errors or server misconfiguration.Retry with backoff; escalate if persistent.
emoji.not_supportedPayload contained characters the database rejects (for example emoji).Strip unsupported characters, then retry.
deprecationThe endpoint version is deprecated.Migrate to the current endpoint version.

Account, balance, and limits (any debiting endpoint):

CodeMeaningRecommended handling
sales.account_balance_insufficientAccount balance cannot cover the amount.Top up the account, then retry with a new externalId.
sales.account_balance_insufficient_no_balanceSame insufficient-balance condition; variant returned on third-party sale routes.Top up, then retry with a new externalId.
account.terminatedThe calling account has been terminated.Contact Whish (not recoverable client-side).
account.dealer.terminatedThe parent dealer account is terminated.Contact Whish.
sales.denomination_not_activeThe requested service/denomination is disabled.Verify the denomination id; retry later or contact Whish.
sales.schema_not_activePricing schema not configured/active for this account and service.Contact Whish (configuration issue).
sales.exceeded_daily_limitDaily amount/count limit reached.Wait for the next day, or request a limit increase.
sales.exceeded_monthly_limitMonthly limit reached.Wait, or request a limit increase.
sales.lost_transactions_existEarlier transaction results were not acknowledged.Query the status of prior transactions (replay their externalIds) before submitting new ones.
account.topup.check.condition.fail (surfaced as transfer.failed.title)The receiving account would exceed its maximum allowed wallet balance.Final failure; the receiver must reduce balance or verify their account.
currency.not_supported / invalid_currencyThe currency is not enabled or recognized for this route (typically only LBP and USD).Send a supported currency.
fatalInternal failure while registering the externalId (defensive path; not expected in practice).Retry with the same externalId; escalate if persistent.

Version history

Notable changes to this API and its reference, newest first. The current version is the one shown at the top of this page.

VersionDateChange
v1.02026-07-15Pre-release documentation update: error-code reference added; externalId documented as a String; sandbox base URL updated.
v1.02026-02-24Initial release.

Postman & tools

Import the ready-made Postman collection for this API, set your credentials as collection variables (or attach a sandbox / production environment), and call every endpoint without writing code. The OpenAPI 3.1 specification is also available to generate client SDKs or validate requests.

Download collectionOpenAPI specAll downloads & environments

In Postman: Import → select the file → choose the Sandbox or Production environment → fill in your credentials. Requests use {{baseUrl}} and the credential variables provided.