SwitchLock Docs
API Reference/Payments

Payments

Deposit funds, generate escrow-backed payment links, manage the checkout flow, and retrieve transaction records. Most endpoints require a valid x-api-key and x-company-id header.

All monetary amounts are expressed in cents. USD 10.00 = 1000. The minimum accepted value is 1.

Deposits

POST
/v1/payments/deposit

Record a deposit into a company or user account. Supports idempotency — send an x-idempotency-key header to deduplicate retries.

Auth
FieldTypeRequiredDescription
userIduuidNoAssign deposit to a specific user; omit for a company-level deposit.
amountintegerYesAmount in cents (minimum 1).
currencyenumYesUSD or ZIG.
externalReferencestringNoYour system's reference ID for this deposit.
userReferencestringNoHuman-readable memo shown to the user.
isTransitbooleanNoMark the deposit as in-transit (not yet settled). Defaults to false.
curl -X POST "https://api.switchlock.co.zw/v1/payments/deposit" \
  -H "x-api-key: zl_sk_your_key_here" \
  -H "x-company-id: cmp_01HXYZ..." \
  -H "Content-Type: application/json" \
  -d '{
  "userId": "string",
  "amount": 1000,
  "currency": "string",
  "externalReference": "string",
  "userReference": "string",
  "isTransit": true
}'
Response Example
{
  "id": "txn_01hx...",
  "type": "DEPOSIT",
  "amount": "5000",
  "currency": "USD",
  "status": "COMPLETED",
  "createdAt": "2026-06-23T10:00:00.000Z"
}

Escrow Payment Links

Generate a shareable URL that takes a buyer through a hosted checkout, funding an escrow automatically on completion.

POST
/v1/payments/generate-escrow-payment-link

Create an escrow-backed payment link. Returns a hash the buyer visits to pay.

Auth
FieldTypeRequiredDescription
buyerIduuidYesUUID of the buyer user.
sellerIduuidNoUUID of the seller; uses company default if omitted.
amountintegerYesTotal amount in cents.
currencyenumYesUSD or ZIG.
itemsarrayYesLine items — each with name, quantity, pricePerUnit.
externalReferencestringNoYour internal reference for this order.
userReferencestringNoMemo shown to the buyer at checkout.
splitPlanobjectNoCustom fee split: system_fee_cents, service_fee_cents, seller_payout_cents. Must sum to amount.
curl -X POST "https://api.switchlock.co.zw/v1/payments/generate-escrow-payment-link" \
  -H "x-api-key: zl_sk_your_key_here" \
  -H "x-company-id: cmp_01HXYZ..." \
  -H "Content-Type: application/json" \
  -d '{
  "buyerId": "string",
  "sellerId": "string",
  "amount": 1000,
  "currency": "string",
  "items": [],
  "externalReference": "string",
  "userReference": "string",
  "splitPlan": {}
}'
Response Example
{
  "hash": "pay_8f3kz...",
  "url": "https://checkout.switchlock.com/pay/pay_8f3kz...",
  "expiresAt": "2026-06-30T10:00:00.000Z",
  "escrowId": "esc_01hx..."
}
GET
/v1/payments/link-details/:hash

Fetch the current state and metadata of a payment link by its hash.

Public
FieldTypeRequiredDescription
hashstring (path)YesThe hash returned when the link was generated.
curl -X GET "https://api.switchlock.co.zw/v1/payments/link-details/value"
Response Example
{
  "hash": "pay_8f3kz...",
  "status": "PENDING",
  "amount": 5000,
  "currency": "USD",
  "buyer": { "id": "...", "name": "Tendai M." },
  "items": [{ "name": "Web Design", "quantity": 1, "pricePerUnit": 5000 }]
}

Checkout Flow

These endpoints power the hosted checkout UI. They are all public — no API key required. Call them in sequence to guide a buyer through identity verification and payment acceptance.

These endpoints are intended for the hosted checkout front end. Calling them directly from a server integration is not the standard flow — use generate-escrow-payment-link instead.

POST
/v1/payments/request-checkout-otp

Send a one-time password to the buyer's WhatsApp number to verify identity before checkout.

Public
FieldTypeRequiredDescription
whatsappNumberstringYesBuyer's WhatsApp number in E.164 format (e.g. +263771234567).
curl -X POST "https://api.switchlock.co.zw/v1/payments/request-checkout-otp" \
  -H "Content-Type: application/json" \
  -d '{
  "whatsappNumber": "string"
}'
Response Example
{ "sent": true, "expiresIn": 300 }
POST
/v1/payments/register-checkout-user

Register a new buyer during checkout if they are not yet in the system.

Public
FieldTypeRequiredDescription
mobileNumberstringYesBuyer's mobile number.
idNumberstringYesZimbabwean National ID number.
firstNamestringNoBuyer's first name.
lastNamestringNoBuyer's last name.
curl -X POST "https://api.switchlock.co.zw/v1/payments/register-checkout-user" \
  -H "Content-Type: application/json" \
  -d '{
  "mobileNumber": "string",
  "idNumber": "string",
  "firstName": "string",
  "lastName": "string"
}'
Response Example
{ "userId": "usr_01hx...", "status": "REGISTERED" }
POST
/v1/payments/accept-payment

Accept a pending payment link after the buyer has verified their identity.

Public
FieldTypeRequiredDescription
paymentSlugstringYesHash of the payment link to accept.
phoneNumberstringNoBuyer's phone number (used for mobile money).
whatsappNumberstringNoBuyer's WhatsApp number.
otpstringNoOTP received via WhatsApp.
curl -X POST "https://api.switchlock.co.zw/v1/payments/accept-payment" \
  -H "Content-Type: application/json" \
  -d '{
  "paymentSlug": "string",
  "phoneNumber": "string",
  "whatsappNumber": "string",
  "otp": "string"
}'
Response Example
{ "status": "ACCEPTED", "escrowId": "esc_01hx...", "transactionId": "txn_..." }
POST
/v1/payments/reject-payment

Reject a pending payment link — funds are not captured.

Public
FieldTypeRequiredDescription
paymentSlugstringYesHash of the payment link to reject.
curl -X POST "https://api.switchlock.co.zw/v1/payments/reject-payment" \
  -H "Content-Type: application/json" \
  -d '{
  "paymentSlug": "string"
}'
Response Example
{ "status": "REJECTED" }

EFT Checkout

Powered by Oppwa

Initiate and verify card or EFT payments through the Oppwa (HPS) gateway. The webhook endpoint is called server-to-server by Oppwa.

POST
/v1/payments/eft-pay/initiate

Start an EFT checkout session for a given payment link. Returns a checkoutId to mount the Oppwa widget.

Public
FieldTypeRequiredDescription
paymentSlugstringYesHash of the payment link to fund via EFT.
curl -X POST "https://api.switchlock.co.zw/v1/payments/eft-pay/initiate" \
  -H "Content-Type: application/json" \
  -d '{
  "paymentSlug": "string"
}'
Response Example
{ "checkoutId": "ch_8f3kz..." }
POST
/v1/payments/eft-pay/verify

Verify an EFT payment after the Oppwa widget completes. Called client-side with the resourcePath from the widget callback.

Public
FieldTypeRequiredDescription
resourcePathstringYesThe resourcePath provided by the Oppwa widget on completion (e.g. /v1/checkouts/{id}/payment).
curl -X POST "https://api.switchlock.co.zw/v1/payments/eft-pay/verify" \
  -H "Content-Type: application/json" \
  -d '{
  "resourcePath": "string"
}'
Response Example
{ "status": "COMPLETED", "transactionId": "txn_..." }
POST
/v1/payments/eft-pay/webhook

Oppwa server-to-server webhook. SwitchLock uses the id in the payload to re-verify the payment securely. Always returns 200 OK.

Public
FieldTypeRequiredDescription
idstringNoCheckout ID from Oppwa (preferred).
payloadobjectNoFallback: Oppwa may nest the ID here as payload.id.
curl -X POST "https://api.switchlock.co.zw/v1/payments/eft-pay/webhook" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "string",
  "payload": {}
}'
Response Example
{ "status": "OK" }

Transactions

GET
/v1/payments/transaction/:id

Retrieve a single transaction record by its UUID.

Auth
FieldTypeRequiredDescription
idstring (path)YesUUID of the transaction to retrieve.
curl -X GET "https://api.switchlock.co.zw/v1/payments/transaction/value" \
  -H "x-api-key: zl_sk_your_key_here" \
  -H "x-company-id: cmp_01HXYZ..."
Response Example
{
  "id": "txn_01hx...",
  "type": "ESCROW_HOLD",
  "amount": "10000",
  "currency": "USD",
  "status": "COMPLETED",
  "metadata": {},
  "createdAt": "2026-06-23T10:00:00.000Z"
}

Authentication

All non-public endpoints require two headers on every request.

Required headers
x-api-key: your_api_key_here
x-company-id: your_company_uuid

Public endpoints (marked Public above) do not require these headers — they are accessible from a browser directly.

Next steps