Submit a bank account change with the API

Validate, create, and track a bank account change with the Case Management API
View as MarkdownOpen in Claude
Applies to:DevelopersPartners
Bank account change access requires configuration by the Payabli team. Contact us to get started.

This guide walks through submitting a bank account change with the Case Management API: validate the account, create the case, and track it as verification runs. For the states a case moves through and who can act on it, see Bank account change lifecycle.

Prerequisites

Before you start, make sure you have:

  • Case Management access enabled for your organization. Contact the Payabli team if you’re not sure.
  • An OAuth Bearer token. These endpoints authenticate with a Bearer token, not the requestToken API key. See OAuth authentication.
  • The numeric ID of the paypoint whose account you’re changing.

The examples use the sandbox base URL, https://api-sandbox.payabli.com/api. Switch to https://api.payabli.com/api for production.

Steps

These steps take you from validating the account through to a completed change.

1

Validate the request

Before you create a case, validate the account details. Validation runs the same checks as creation without saving anything, so you can catch problems first.

POST
/api/v2/cases/bank-account/:paypointId/validate
1curl -X POST https://api-sandbox.payabli.com/api/v2/cases/bank-account/3040/validate \
2 -H "Content-Type: application/json" \
3 -d '{
4 "routingNumber": "123456789",
5 "accountNumber": "987654321",
6 "accountType": "checking",
7 "bankAccountHolderType": "business",
8 "bankAccountFunction": "Deposits",
9 "services": {
10 "moneyIn": [
11 "Ach"
12 ],
13 "moneyOut": [
14 "Ach"
15 ]
16 }
17}'

The response tells you whether the request is valid:

Response
1{
2 "isValid": true,
3 "blockingConditions": [],
4 "warnings": [
5 "This paypoint has active batches. Consider scheduling the bank account change after the current batch is closed."
6 ],
7 "validationErrors": []
8}

Resolve any blockingConditions before you continue. warnings are informational, so you can create the case with them present.

2

Create the case

Once validation passes, create the case. Add a nickname, a bankName, and default to the same details you validated. Payabli tokenizes the account and takes the account holder name from the paypoint’s legal name.

POST
/api/v2/cases/bank-account/:paypointId
1curl -X POST https://api-sandbox.payabli.com/api/v2/cases/bank-account/3040 \
2 -H "Content-Type: application/json" \
3 -d '{
4 "nickname": "Main Settlement Account",
5 "bankName": "First National Bank",
6 "routingNumber": "123456789",
7 "accountNumber": "987654321",
8 "accountType": "checking",
9 "bankAccountHolderType": "business",
10 "bankAccountFunction": "Deposits",
11 "services": {
12 "moneyIn": [
13 "Ach"
14 ],
15 "moneyOut": [
16 "Ach"
17 ]
18 },
19 "default": true
20}'

To run the change later instead of right after approval, add a scheduleFor UTC timestamp between 1 hour and 30 days out. Payabli verifies and reviews the case right away, then waits until that time to complete the switch.

A 201 response returns the full case in the Submitted state. Save the uuid — you’ll use it to track the case. The raw account and routing numbers aren’t returned; the case carries a bankToken instead.

Response
1{
2 "uuid": "9c2b7e14-3a5f-4d21-b8e0-1f6a4c9d2e70",
3 "state": "Submitted",
4 "caseType": "BankAccountChange",
5 "parameters": {
6 "type": "BankAccountChange",
7 "nickname": "Main Settlement Account",
8 "bankName": "First National Bank",
9 "bankToken": "bnk_2b1c9e40f5a34c9a8f219e7c6b1a2d34",
10 "accountType": "Checking",
11 "bankAccountHolderName": "Gruzya Adventure Outfitters LLC",
12 "bankAccountHolderType": "business",
13 "bankAccountFunction": "Deposits",
14 "services": {
15 "moneyIn": [
16 "Ach"
17 ],
18 "moneyOut": [
19 "Ach"
20 ]
21 },
22 "default": true
23 },
24 "orgId": 123,
25 "paypointId": 3040,
26 "scheduleFor": null,
27 "createdAt": "2026-01-15T10:30:00Z",
28 "updatedAt": "2026-01-15T10:30:00Z",
29 "createdBy": 0,
30 "assigneeId": null,
31 "lastReviewedById": null,
32 "stateHistory": [],
33 "attachments": [],
34 "roomId": null,
35 "metadata": null,
36 "org": {
37 "id": 123,
38 "name": "Example Partner Org"
39 },
40 "paypoint": {
41 "id": 3040,
42 "name": "Gruzya Adventure Outfitters"
43 },
44 "createdByUser": null,
45 "assignee": null,
46 "lastReviewedBy": null
47}
3

Track verification

After creation, the case moves to Verifying on its own and automatic verification runs. Fetch the case to check its status.

GET
/api/v2/cases/:uuid
1curl https://api-sandbox.payabli.com/api/v2/cases/9c2b7e14-3a5f-4d21-b8e0-1f6a4c9d2e70

Verification resolves to one of three states:

  • AutoApproved — the account passed cleanly and moves toward completion.
  • PendingReview — the result was inconclusive and needs a reviewer.
  • Denied — the account failed verification. This is final.

The outcome appears in metadata.verification once verification finishes:

Response
1{
2 "uuid": "9c2b7e14-3a5f-4d21-b8e0-1f6a4c9d2e70",
3 "state": "PendingCompletion",
4 "caseType": "BankAccountChange",
5 "parameters": {
6 "type": "BankAccountChange",
7 "nickname": "Main Settlement Account",
8 "bankName": "First National Bank",
9 "bankToken": "bnk_2b1c9e40f5a34c9a8f219e7c6b1a2d34",
10 "accountType": "Checking",
11 "bankAccountHolderName": "Gruzya Adventure Outfitters LLC",
12 "bankAccountHolderType": "business",
13 "bankAccountFunction": "Deposits",
14 "services": {
15 "moneyIn": [
16 "Ach"
17 ],
18 "moneyOut": [
19 "Ach"
20 ]
21 },
22 "default": true
23 },
24 "orgId": 123,
25 "paypointId": 3040,
26 "scheduleFor": null,
27 "createdAt": "2026-01-15T10:30:00Z",
28 "updatedAt": "2026-01-15T10:30:43Z",
29 "createdBy": 0,
30 "assigneeId": null,
31 "lastReviewedById": null,
32 "stateHistory": [
33 {
34 "uuid": "019f806f-453f-701c-b77d-cb585b743bef",
35 "caseUuid": "9c2b7e14-3a5f-4d21-b8e0-1f6a4c9d2e70",
36 "fromState": "Submitted",
37 "toState": "Verifying",
38 "ipAddress": null,
39 "triggeredBy": null,
40 "reason": "Background verification started",
41 "createdAt": "2026-01-15T10:30:03Z",
42 "triggeredByUser": null
43 },
44 {
45 "uuid": "019f806f-e00e-73d2-b6a4-9dd5b540e11e",
46 "caseUuid": "9c2b7e14-3a5f-4d21-b8e0-1f6a4c9d2e70",
47 "fromState": "Verifying",
48 "toState": "AutoApproved",
49 "ipAddress": null,
50 "triggeredBy": null,
51 "reason": "Polling outcome: approved",
52 "createdAt": "2026-01-15T10:30:43Z",
53 "triggeredByUser": null
54 },
55 {
56 "uuid": "019f806f-e015-730b-be18-ec695f42f133",
57 "caseUuid": "9c2b7e14-3a5f-4d21-b8e0-1f6a4c9d2e70",
58 "fromState": "AutoApproved",
59 "toState": "PendingCompletion",
60 "ipAddress": null,
61 "triggeredBy": null,
62 "reason": "funding hold acquired",
63 "createdAt": "2026-01-15T10:30:43Z",
64 "triggeredByUser": null
65 }
66 ],
67 "attachments": [],
68 "roomId": 96369,
69 "metadata": {
70 "verification": {
71 "verificationResult": {
72 "code": 6,
73 "name": "Pass",
74 "description": "The suggested action is to accept the bank account and/or customer data for this inquiry."
75 },
76 "accountResponseCode": {
77 "code": 12,
78 "name": "_1111",
79 "description": "Account Verified – The account was found to be an open and valid checking account."
80 },
81 "customerResponseCode": null
82 },
83 "reviewDecision": null
84 },
85 "org": {
86 "id": 123,
87 "name": "Example Partner Org"
88 },
89 "paypoint": {
90 "id": 3040,
91 "name": "Gruzya Adventure Outfitters"
92 },
93 "createdByUser": null,
94 "assignee": null,
95 "lastReviewedBy": null
96}

Poll the case rather than waiting on the create call, since the flow is asynchronous.

4

Review the case (Enterprise Partners)

If a case is PendingReview, an Enterprise Partner acts on it. Platform Partners skip this step — Payabli makes the decision, and the case moves to Approved or Denied on its own.

First check which actions are available:

GET
/api/v2/cases/:uuid/transitions
1curl https://api-sandbox.payabli.com/api/v2/cases/9c2b7e14-3a5f-4d21-b8e0-1f6a4c9d2e70/transitions

Assign the case to a reviewer with the assign endpoint:

POST
/api/v2/cases/:uuid/assign
1curl -X POST https://api-sandbox.payabli.com/api/v2/cases/9c2b7e14-3a5f-4d21-b8e0-1f6a4c9d2e70/assign \
2 -H "Content-Type: application/json" \
3 -d '{
4 "assigneeId": 4238,
5 "reason": "Routing to the risk team for review."
6}'

Approve or deny the case with the transitions endpoint. Include a declineReason when you deny.

POST
/api/v2/cases/:uuid/transitions
1curl -X POST https://api-sandbox.payabli.com/api/v2/cases/9c2b7e14-3a5f-4d21-b8e0-1f6a4c9d2e70/transitions \
2 -H "Content-Type: application/json" \
3 -d '{
4 "trigger": "Approve",
5 "reason": "Account ownership confirmed with the merchant by phone."
6}'

A successful call returns the updated case with its new state and a new stateHistory entry recording the action.

Response
1{
2 "uuid": "9c2b7e14-3a5f-4d21-b8e0-1f6a4c9d2e70",
3 "state": "Approved",
4 "caseType": "BankAccountChange",
5 "parameters": {
6 "type": "BankAccountChange",
7 "nickname": "Main Settlement Account",
8 "bankName": "First National Bank",
9 "bankToken": "bnk_2b1c9e40f5a34c9a8f219e7c6b1a2d34",
10 "accountType": "Checking",
11 "bankAccountHolderName": "Gruzya Adventure Outfitters LLC",
12 "bankAccountHolderType": "business",
13 "bankAccountFunction": "Deposits",
14 "services": {
15 "moneyIn": [
16 "Ach"
17 ],
18 "moneyOut": [
19 "Ach"
20 ]
21 },
22 "default": true
23 },
24 "orgId": 123,
25 "paypointId": 3040,
26 "scheduleFor": null,
27 "createdAt": "2026-01-15T10:30:00Z",
28 "updatedAt": "2026-01-15T12:15:00Z",
29 "createdBy": 0,
30 "assigneeId": 4238,
31 "lastReviewedById": 4238,
32 "stateHistory": [
33 {
34 "uuid": "019f8100-1a2b-73c4-9d5e-6f7a8b9c0d1e",
35 "caseUuid": "9c2b7e14-3a5f-4d21-b8e0-1f6a4c9d2e70",
36 "fromState": "Assigned",
37 "toState": "Approved",
38 "ipAddress": "203.0.113.10",
39 "triggeredBy": 4238,
40 "reason": "Account ownership confirmed with the merchant by phone.",
41 "createdAt": "2026-01-15T12:15:00Z",
42 "triggeredByUser": {
43 "id": 4238,
44 "name": "Jordan Rivera"
45 }
46 }
47 ],
48 "attachments": [],
49 "roomId": 96370,
50 "metadata": {
51 "verification": {
52 "verificationResult": {
53 "code": 5,
54 "name": "RiskAlert",
55 "description": "The suggested action is to further investigate the bank account and/or customer data for this inquiry due to a risk alert ."
56 },
57 "accountResponseCode": {
58 "code": 12,
59 "name": "_1111",
60 "description": "Account Verified – The account was found to be an open and valid checking account."
61 },
62 "customerResponseCode": {
63 "code": 3,
64 "name": "CA21",
65 "description": "The customer or business name data did not match gAuthenticate data."
66 }
67 },
68 "reviewDecision": null
69 },
70 "org": {
71 "id": 123,
72 "name": "Example Partner Org"
73 },
74 "paypoint": {
75 "id": 3040,
76 "name": "Gruzya Adventure Outfitters"
77 },
78 "createdByUser": null,
79 "assignee": {
80 "id": 4238,
81 "name": "Jordan Rivera"
82 },
83 "lastReviewedBy": {
84 "id": 4238,
85 "name": "Jordan Rivera"
86 }
87}

Firing an action that isn’t valid for the case’s current state returns a 409. Use the transitions list to confirm what’s allowed first.

5

Confirm completion

An approved case moves to PendingCompletion while the account switch runs, then to Completed when the processor confirms it. Fetch the case one more time to confirm it reached Completed.

PendingCompletion typically clears in under a minute. If a case stays there for more than an hour, contact the Payabli team rather than resubmitting.

See these related resources to help you get the most out of Payabli.