API integration guide

Guide to integrating the automated bank slip verification API, for merchants and developers

Base URL

The base for every endpoint in this guide

https://api.slip2try.com

API version v1 (every endpoint lives under /api/v1) · last updated 2026-10-23

API v1

Create an API key → send a slip verification request → review the history

3 steps
  1. Step 1

    Create an API key

    After signing up, open the API keys page and create a key (none is created automatically). The secret is shown only once — copy it and keep it on your server.

  2. Step 2

    Send the slip QR for verification

    Read the QR value from the slip (it starts with 00...) and send it to POST /api/v1/verify/slip

    The response includes data.transfer with the actual amount, and duplicate tells you whether the slip is a duplicate
  3. Step 3

    Review every past result

    Every request is logged. Click a row to see the slip details, sender, receiver, amount and source IP.

8 things to get right before you take real payments

Must do
  1. 1Call the API only from your server — never ship the key in web pages or apps · build against an s2t_test_ key, then switch to s2t_live_ for production
  2. 2Send expectedAmount = the order total with every slip
  3. 3Deliver only when success && !duplicate && warnings.length === 0 && environment === "live" — anything else is rejected or goes to manual review
  4. 4Read transfer details from data.transfer · store transactionRef as a unique key and keep verificationId with the order
  5. 5Branch on success + reason only — never on the message text
  6. 6Use a 60-second client timeout · on a timeout or dropped connection, look the result up with GET /api/v1/verifications?qrData= (or ?requestId=) before resending
  7. 7On 429 or 503, wait Retry-After seconds before retrying · queue bulk work (120 requests/min per shop by default)
  8. 8Webhooks: verify X-VerifySlips-Signature-V2 over the raw body and reject timestamps more than 5 minutes off · dedupe on the body id · answer 2xx within 10 seconds

On the left is the request code; on the right are the decoded slip fields and the verified bank logos.

HTTP 200 · Successful

Request code

POST /api/v1/verify/slip

# Deliver only when success: true, duplicate: false, warnings: [] and environment: "live" · expectedAmount = order total
curl -X POST https://api.slip2try.com/api/v1/verify/slip \
  --max-time 60 \
  -H "Authorization: Bearer s2t_live_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"qrData":"0038000600000101030060217A3828f7b4f3244ff35102TH910480CE","expectedAmount":100000}'

# Timeout or dropped connection: look the result up before resending (uses no quota)
curl -G https://api.slip2try.com/api/v1/verifications \
  --max-time 60 \
  -H "Authorization: Bearer s2t_live_xxxxxxxx" \
  --data-urlencode "qrData=0038000600000101030060217A3828f7b4f3244ff35102TH910480CE"

Decoded slip example

Krungthai Bank

Krungthai Business · Krungthai Bank

Verified against the bank

ktb

Amount transferred

100,000.00 THB

Krungthai Bank

Sender account

น.ส.สมศรี ใจดี

Krungthai Bank · XX123-4
SCB

Receiver account

EXAMPLE CO., LTD.

SCB · XX567-8
transactionRef
A3828f7b4f3244ff3
transactionDateTime
2026-09-01T17:51:01+07:00
amount.amount
100,000.00 THB
duplicate
false · new slip

Same structure for every provider

Write code to read data.transfer once and it works with KTB, CIMB, SCB and Slip2Go right away.

Check duplicate every time before crediting or shipping

Check before delivering

How to read the result

ResponseResultWhat to do
success: true · duplicate: falseNew slipTop up / ship the order
success: true · duplicate: trueDuplicate slipReject — the customer may be reusing a slip
success: falseNot verifiedDon't deliver; ask the customer to check the slip

The first verification returns duplicate: false and duplicateInfo: null

Sample response for a duplicate slip

Response · Duplicate slip
{
  "success": true,
  "cached": true,
  "duplicate": true,
  "duplicateInfo": {
    "firstVerifiedAt": "2026-10-14T04:14:49.145Z",
    "previousCount": 2
  },
  "data": { "...": "Same transfer details as the first verification" }
}
  • Counted per shop

    A slip verified by another shop doesn't count as a duplicate for yours — your first check still uses 1 slip as usual

  • Matched by QR or reference

    The same QR, or a different QR with the same transactionRef, counts as a duplicate — and duplicates use no slips

  • Failed checks don't count

    A verification that failed isn't counted as a previous check

  • Concurrent requests, one winner

    If the same slip is sent in several requests at once, only one gets duplicate: false

  • Webhooks tell you too

    verify.success includes data.duplicate and data.firstVerifiedAt

  • Review it in the portal

    The Verification history page shows a “Duplicate” badge and has a filter for it

Add another layer in your own system

Store transactionRef as a unique key in your order database too, in case your code calls twice or receives a webhook twice.

Try every case with a test key before going live — simulated results, no bank call, no quota used

No quota used

Click an item to expand or collapse it and see the required parameters, a sample request, and what the response looks like on success and failure.

The reason field lets your system tell cases apart and notify users correctly

The maximum number of requests per minute, and what to do when you exceed it

120 requests / min by default

Results are sent to your callback URL automatically for the events you select on the Callback / Webhook page — no polling code needed.

Live

Use these to turn fromBankCode / toBankCode in verification results into bank names and logos (3-digit Bank of Thailand codes)

20 bank codes

Services enabled for your shop, and who to contact when you can't fix something yourself