Skip to content

Batch Async Verify

Submit multiple bank slips in a single request. Each slip is queued as its own async job with its own jobId; results are delivered per-job to your webhook and can be polled individually. Up to 100 slips per request.

Bank only, payload only

Like single async verify, batch is bank-only and each slip is a QR payload string.

Endpoint

http
POST /verify/bank/batch

Full URL: https://api-partners.easyslip.com/v2/verify/bank/batch

Authentication

Required. Uses HMAC-SHA256 with your branch UUID as X-API-Key. See Authentication Guide.

http
X-API-Key: YOUR_BRANCH_UUID
X-Timestamp: 1700000000
X-Nonce: 550e8400-e29b-41d4-a716-446655440000
X-Signature: HMAC_SHA256_SIGNATURE
Content-Type: application/json

Request

Parameters

ParameterTypeRequiredDescription
slipsarrayYes1-100 slip objects (see below)
callbackUrlstringConditionalHTTPS URL results are POSTed to (one per job). Required unless a default webhook URL is configured for the branch. Max 255 chars.

Each object in slips accepts the same per-slip fields as single async verify:

FieldTypeRequiredDescription
payloadstringYesQR code payload (1-128 characters)
remarkstringNoCustom remark (1-255 characters)
matchAccountbooleanNoMatch receiver with registered accounts
matchAmountnumberNoExpected amount to validate
checkDuplicatebooleanNoCheck for duplicate slip (default: false)

All-or-nothing validation

If any slip is invalid (e.g. missing payload), the whole request is rejected with 400 and nothing is queued. callbackUrl applies to every job in the batch and has the same HTTPS + public-address requirements as single async verify.

Request Body

json
{
  "callbackUrl": "https://example.com/webhooks/easyslip",
  "slips": [
    { "payload": "0000000000000000000000000000000000000000000000A", "remark": "Order #1" },
    { "payload": "0000000000000000000000000000000000000000000000B", "remark": "Order #2", "checkDuplicate": true }
  ]
}

Type Definitions

typescript
// Request
interface BatchAsyncVerifyRequest {
  callbackUrl?: string;     // https URL, max 255 chars (required if no branch webhook)
  slips: Array<{
    payload: string;        // 1-128 chars
    remark?: string;
    matchAccount?: boolean;
    matchAmount?: number;
    checkDuplicate?: boolean;
  }>;                       // 1-100 items
}

// Response
interface BatchAsyncVerifyResponse {
  success: true;
  data: {
    batchId: string;                          // UUID grouping this batch
    jobs: Array<{ jobId: string; index: number }>;  // one per submitted slip, in order
  };
  message: string;
}

Examples

bash
curl -X POST https://api-partners.easyslip.com/v2/verify/bank/batch \
  -H "X-API-Key: YOUR_BRANCH_UUID" \
  -H "X-Timestamp: ${TIMESTAMP}" \
  -H "X-Nonce: ${NONCE}" \
  -H "X-Signature: ${SIGNATURE}" \
  -H "Content-Type: application/json" \
  -d '{
    "callbackUrl": "https://example.com/webhooks/easyslip",
    "slips": [
      { "payload": "0000000000000000000000000000000000000000000000A" },
      { "payload": "0000000000000000000000000000000000000000000000B" }
    ]
  }'
javascript
const verifyBankBatch = async (slips, callbackUrl) => {
  const body = JSON.stringify({ callbackUrl, slips });
  const response = await fetch('https://api-partners.easyslip.com/v2/verify/bank/batch', {
    method: 'POST',
    headers: {
      ...signRequest({ method: 'POST', path: '/verify/bank/batch', body, apiKey: 'YOUR_BRANCH_UUID', secretKey: 'YOUR_SECRET_KEY' }),
      'Content-Type': 'application/json'
    },
    body
  });

  const result = await response.json();
  if (!result.success) throw new Error(result.error.message);

  return result.data; // { batchId, jobs: [{ jobId, index }] }
};

// Usage
const { batchId, jobs } = await verifyBankBatch(
  [{ payload: '0000000000000000000000000000000000000000000000A' }],
  'https://example.com/webhooks/easyslip'
);
console.log(batchId, jobs);
typescript
interface Slip { payload: string; remark?: string; matchAccount?: boolean; matchAmount?: number; checkDuplicate?: boolean; }

async function verifyBankBatch(slips: Slip[], callbackUrl: string) {
  const body = JSON.stringify({ callbackUrl, slips });
  const response = await fetch('https://api-partners.easyslip.com/v2/verify/bank/batch', {
    method: 'POST',
    headers: {
      ...signRequest({ method: 'POST', path: '/verify/bank/batch', body, apiKey: process.env.EASYSLIP_API_KEY!, secretKey: process.env.EASYSLIP_SECRET_KEY! }),
      'Content-Type': 'application/json'
    },
    body
  });

  const result = await response.json();
  if (!result.success) throw new Error(result.error?.message || 'Batch verify failed');

  return result.data as { batchId: string; jobs: { jobId: string; index: number }[] };
}
php
function verifyBankBatch(array $slips, string $callbackUrl): array
{
    $data = ['callbackUrl' => $callbackUrl, 'slips' => $slips];

    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => 'https://api-partners.easyslip.com/v2/verify/bank/batch',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_HTTPHEADER => [
            // Use signRequest() helper - see Authentication Guide
            'Content-Type: application/json'
        ],
        CURLOPT_POSTFIELDS => json_encode($data)
    ]);

    $response = curl_exec($ch);
    curl_close($ch);

    $result = json_decode($response, true);
    if (!$result['success']) {
        throw new Exception($result['error']['message']);
    }

    return $result['data'];
}
python
import requests
import os

def verify_bank_batch(slips: list, callback_url: str) -> dict:
    data = {'callbackUrl': callback_url, 'slips': slips}
    response = requests.post(
        'https://api-partners.easyslip.com/v2/verify/bank/batch',
        headers={
            **sign_request('POST', '/verify/bank/batch', data, os.environ['EASYSLIP_API_KEY'], os.environ['EASYSLIP_SECRET_KEY']),
            'Content-Type': 'application/json'
        },
        json=data
    )

    result = response.json()
    if not result['success']:
        raise Exception(result['error']['message'])

    return result['data']

Response

Accepted (202)

json
{
  "success": true,
  "data": {
    "batchId": "7b2e1f10-1c2d-4e3f-9a8b-0c1d2e3f4a5b",
    "jobs": [
      { "jobId": "550e8400-e29b-41d4-a716-446655440000", "index": 0 },
      { "jobId": "660f9511-f3ab-52e5-b827-557766551111", "index": 1 }
    ]
  },
  "message": "Batch queued"
}

index matches the position of each slip in the request slips array. Each jobId behaves exactly like a single async job — it produces its own webhook and is pollable at GET /verify/bank/jobs/:jobId.

Error Responses

Invalid slip in batch (400)

json
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Payload is required and cannot be empty"
  }
}

Too many slips (400)

json
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "slips must not exceed 100 items"
  }
}

Notes

  • Maximum 100 slips per request; split larger workloads into multiple batches.
  • Validation is all-or-nothing — one bad slip rejects the whole request with nothing queued.
  • Each slip becomes an independent job (its own webhook + pollable status); the shared batchId also appears in each job's webhook payload.

Bank Slip Verification API for Thai Banking