Async Bank Verify
Submit a bank slip for asynchronous verification. Instead of blocking until the result is ready, the API immediately returns a jobId; the slip is verified in the background and the result is delivered to your webhook and/or fetched by polling the job.
Use async verification for high-volume / bulk workloads where you don't need the result inline. For a single inline result, use the synchronous POST /verify/bank instead.
Bank only
Async verification is available for bank slips only, and accepts a QR payload string only (no image / base64 / url). TrueWallet has no payload and stays on the synchronous /verify/truewallet route.
Endpoint
POST /verify/bank/asyncFull URL: https://api-partners.easyslip.com/v2/verify/bank/async
Authentication
Required. Uses HMAC-SHA256 with your branch UUID as X-API-Key. See Authentication Guide.
X-API-Key: YOUR_BRANCH_UUID
X-Timestamp: 1700000000
X-Nonce: 550e8400-e29b-41d4-a716-446655440000
X-Signature: HMAC_SHA256_SIGNATURE
Content-Type: application/jsonRequest
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
payload | string | Yes | QR code payload (1-128 characters) |
callbackUrl | string | Conditional | HTTPS URL the result is POSTed to. Required unless a default webhook URL is configured for the branch. Max 255 chars. |
remark | string | No | Custom remark (1-255 characters) |
matchAccount | boolean | No | Match receiver with registered accounts |
matchAmount | number | No | Expected amount to validate |
checkDuplicate | boolean | No | Check for duplicate slip (default: false) |
callbackUrl requirements
callbackUrl must use HTTPS and must resolve to a public address — URLs pointing at private/internal IP ranges are rejected. If you omit callbackUrl, the branch's configured webhook URL is used; if neither is set the request is rejected with VALIDATION_ERROR.
Request Body
{
"payload": "00000000000000000000000000000000000000000000000",
"callbackUrl": "https://example.com/webhooks/easyslip",
"remark": "Order #12345",
"checkDuplicate": true
}Type Definitions
// Request
interface AsyncVerifyBankRequest {
payload: string; // 1-128 chars
callbackUrl?: string; // https URL, max 255 chars (required if no branch webhook)
remark?: string; // 1-255 chars
matchAccount?: boolean;
matchAmount?: number;
checkDuplicate?: boolean;
}
// Response
interface AsyncVerifyResponse {
success: true;
data: {
jobId: string; // UUID — use it to poll GET /verify/bank/jobs/:jobId
};
message: string;
}Examples
curl -X POST https://api-partners.easyslip.com/v2/verify/bank/async \
-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 '{
"payload": "00000000000000000000000000000000000000000000000",
"callbackUrl": "https://example.com/webhooks/easyslip",
"checkDuplicate": true
}'const verifyBankAsync = async (payload, callbackUrl, options = {}) => {
const body = JSON.stringify({ payload, callbackUrl, ...options });
const response = await fetch('https://api-partners.easyslip.com/v2/verify/bank/async', {
method: 'POST',
headers: {
...signRequest({ method: 'POST', path: '/verify/bank/async', 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.jobId;
};
// Usage
const jobId = await verifyBankAsync(
'00000000000000000000000000000000000000000000000',
'https://example.com/webhooks/easyslip',
{ checkDuplicate: true }
);
console.log('Queued job:', jobId);interface AsyncOptions {
remark?: string;
matchAccount?: boolean;
matchAmount?: number;
checkDuplicate?: boolean;
}
async function verifyBankAsync(payload: string, callbackUrl: string, options: AsyncOptions = {}): Promise<string> {
const body = JSON.stringify({ payload, callbackUrl, ...options });
const response = await fetch('https://api-partners.easyslip.com/v2/verify/bank/async', {
method: 'POST',
headers: {
...signRequest({ method: 'POST', path: '/verify/bank/async', 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 || 'Async verify failed');
return result.data.jobId;
}function verifyBankAsync(string $payload, string $callbackUrl, array $options = []): string
{
$data = array_merge(['payload' => $payload, 'callbackUrl' => $callbackUrl], $options);
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://api-partners.easyslip.com/v2/verify/bank/async',
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']['jobId'];
}import requests
import os
def verify_bank_async(payload: str, callback_url: str, **options) -> str:
data = {'payload': payload, 'callbackUrl': callback_url, **options}
response = requests.post(
'https://api-partners.easyslip.com/v2/verify/bank/async',
headers={
**sign_request('POST', '/verify/bank/async', 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']['jobId']Response
Accepted (202)
{
"success": true,
"data": {
"jobId": "550e8400-e29b-41d4-a716-446655440000"
},
"message": "Verification job queued"
}A 202 Accepted means the job was queued — not that the slip was verified. Wait for the webhook, or poll the job with the returned jobId.
Error Responses
Missing Payload / callbackUrl (400)
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Payload is required and cannot be empty"
}
}Invalid callbackUrl (400)
{
"success": false,
"error": {
"code": "INVALID_CALLBACK_URL",
"message": "callbackUrl must use the https protocol"
}
}Rate Limit Exceeded (429)
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded"
}
}See Rate Limits for the X-RateLimit-* and Retry-After headers.
Notes
- The response
jobIdis a UUID; store it to correlate the webhook and to poll job status. - Results are delivered to your webhook (see Webhooks); polling is a fallback.
- To submit many slips in one request, use POST /verify/bank/batch (up to 100 slips).
- Async is payload-only — for image / URL verification use the synchronous POST /verify/bank.