Sama AlThawaf API

Reference documentation and live tester for the Sama AlThawaf payment & top-up platform.

Connection settings
No credentials set.

Introduction

What the API is, how it is organised, and what is needed before getting started.

The Sama AlThawaf API lets clients buy prepaid products (pulsa, packages, token listrik) and pay bills on behalf of their customers. Every resource lives under the /api/v2 base path and speaks JSON over HTTPS.

ItemValue
Base URLhttps://<host>/api/v2
Content Typeapplication/json
AuthenticationPer-request headers, see Authentication
Response envelope{"code": <int>, "status": <string>, "data": <...>}

Resources

ResourcePurpose
AccountOwn account details and platform balance.
ProductsCatalog of products available to the account.
TransactionsTop-up purchases, lookups, and historical reports.
BillsBill inquiry and bill payment (e.g. Telkomsel OMNI).
Idempotency

Always send a unique transactionId for mutating calls (top-up, bill pay). The platform rejects duplicate IDs, so re-sending the same request cannot double-charge the customer.

Authentication

Every endpoint, except none. All API endpoints require credentials.

Authentication uses two headers on every request. A client receives a User ID and a secret API key when the account is provisioned. Keep the API key private; anyone holding it can use the account balance.

HeaderDescription
useridThe account’s user ID, e.g. thawaf or the client platform ID.
api-keySecret client key bound to the account.

Example request headers

userid: 
api-key: 
Content-Type: application/json   <!-- only for POST & PUT bodies -->
Invalid or missing credentials

Requests without a valid key return 401 with {"code": 401, "status": "Error", "detail": "key tidak sesuai, silahkan hubungi cs"}. Missing headers fall through to the generic 404 error response.

Response format

Success, pending, and error responses all use the same envelope.

Every response is a JSON object with three keys:

KeyTypeDescription
codeintegerStatus code. Matches the HTTP status.
statusstringHuman status: Success, Pending, or Error.
dataobject | array | nullPayload. Omitted on plain errors, where detail is used instead.
detailstringError message. Present only in error responses.

Success

{
  "code": 200,
  "status": "Success",
  "data": { }
}

Pending (mutating calls queued for processing)

{
  "code": 201,
  "status": "Pending",
  "data": { }
}

Error

{
  "code": 400,
  "status": "Error",
  "detail": "Produk tidak tersedia"
}

Status codes

200
Success: request completed.
201
Pending: accepted, being processed.
400
Bad request: invalid data or duplicate id.
401
Unauthorized: bad API key or unknown user.
404
Not found: wrong path or missing headers.
500
Server error: supplier failure / internal issue.

Webhooks

How the platform notifies clients when an async transaction finishes.

Top-ups and bill payments run asynchronously. When a transaction settles, the platform POSTs the final transaction object to the callback URL configured on the account (stored as the client url.callback).

ItemValue
MethodPOST
Content Typeapplication/json
BodyA full transaction object (same shape as the data of a transaction response)
TimeoutThe callback should accept connections on user.client.url.callback.

Example callback payload

{
  "transactionId": "TRX-20260907-0001",
  "refId": "SAT2409070000001",
  "date": "2026-09-07T08:30:00.000Z",
  "product": {
    "code": "TLKOM10",
    "name": "Telkomsel 10.000",
    "detail": "Paket isi ulang Telkomsel 10k",
    "category": "Mobile",
    "type": "Prepaid",
    "price": 12000,
    "status": "Active",
    "operator": "Telkomsel"
  },
  "customerId": "081234567890",
  "price": 12000,
  "priceAdminFee": 0,
  "priceDisclaimer": 0,
  "priceSubTotal": 12000,
  "action": "Top Up",
  "payment": {
    "status": "Success",
    "method": { "id": "sat-deposit", "name": "Sama alThawaf Deposit", "disclaimer": 0 }
  },
  "sn": "7755112233",
  "message": "Pembelian Telkomsel 10.000 Ke 081234567890 berhasil, SN = 7755112233",
  "note": "",
  "status": "Success",
  "userId": "",
  "user": {
    "userId": "",
    "name": "",
    "email": "ops@example.com",
    "status": "Active",
    "validate": true,
    "platform": { "key": "***", "balance": 975000 }
  },
  "code": 200
}
Recommended flow

Submit a top-up → receive 201 Pending → poll GET /transaction/detail with the transactionId, or simply wait for the webhook. Reply to the webhook with HTTP 200 as fast as possible; retries are not guaranteed.