Disbursement Error Handling

Overview

When making payments to workers, robust handling of error cases is a necessity to ensure money is moved correctly. After using Create Disbursement, check the HTTP response status code and the disbursement's status to determine followup actions.

  • If a 200 or a 201 is returned, the request was successful and no action is required.
  • If a 500, a 504, or a 202 with status = PENDING is returned, the request result is temporarily uncertain and should be polled.
  • If a 400 or a 429 is returned, the request failed due to misconfiguration or rate limiting.
  • If a 202 with status = FAILED is returned, the request failed and should be resolved before retrying the disbursement. Check the reason_code to determine resolution actions.
    • After confirming the disbursement status = FAILED, a disbursement can be safely retried if desired.

Check the HTTP Response Status Code

CodeConditionActions
200A matching disbursement already exists, status is CANCELED or SKIPPEDCan be retried if CANCELED.
Can be updated and reattempted if SKIPPED.
201A new disbursement was created, status is SCHEDULED or COMPLETEDCan be canceled if SCHEDULED.
Can be updated and reattempted or reversed if COMPLETED.
202A new disbursement was attempted, status is PENDING or FAILEDCan be polled if PENDING.
Can be resolved then retried if FAILED.
400A static request validation is incorrect or no invoice configuration is found for the request

If static request validation failed, inspect the response and fix the request accordingly.

If no invoice configuration was found, then contact Support or your Account Manager.

429Too many actual requests are being sent to the API, or the org has exceeded their daily disbursement limit.If rate-limited, handle by waiting with exponential backoff.
Otherwise, contact Support or your Account Manager about potentially increasing the daily disbursement limit.
500Unexpected ErrorPoll to check if the error automatically resolves. If the problem persists, contact Support or your Account Manager with any additional information that can be provided.
504Disbursement request timed out on initial attempt and fallback retryPoll to reattempt the payout. If the problem persists, contact Support or your Account Manager.

Poll Temporary States for Completion

Upon using Create Disbursement, the response might indicate an intermittent failure or intermediate state. These cases should be polled until a terminal state is returned.

Perform polling by repeating Create Disbursement with external_id and type set to match the original request. Poll for completion every 10 seconds 2-3 times, then exponentially back off to 15 min -> 30 min -> 60 min.

An HTTP 500 response is an intermittent failure caused by an unhandled exception from a dependency of Branch's systems. Polling can detect when the dependency resumes normal functionality. Contact Branch with any additional information about these errors to resolve them more quickly.

An HTTP 504 response is an intermittent failure caused by a timeout from a dependency of Branch's systems. Polling will retry the request until the dependency responds within the allotted timeframe.

An HTTP 202 response where the disbursement's status = PENDING is an intermediate state where it's not yet known if the payment will be COMPLETED or FAILED. Polling will query the existing disbursement for the updated status.

Check the Reason Code

Pending Disbursements

If the status of a disbursement is PENDING, poll to query the finalized status.

Reason CodeDescriptionSuggested Action
PAYOUT_PENDINGThe disbursement is still in progress.Poll for completion every 10 seconds 2-3 times, then exponentially back off to 15 min -> 30 min -> 60 min

Skipped Disbursements

If the status of a disbursement is COMPLETED or SKIPPED, the request must be updated with unique external_id or metadata before reattempting.

Reason CodeDescriptionSuggested Action
RETRY_PERIOD_ELAPSEDThe disbursement already existed and is too old to be attempted again.A new payout with unique external_id will need to be created to replace the expired one
RETRY_LIMIT_EXCEEDEDThe disbursement has been retried the max number of allowed attempts (100).A new payout with unique external_id will need to be created to replace the expired one
LIKELY_MATCH_FOUNDThe disbursement was not attempted because another disbursement was identified as a duplicate.Review payout to ensure it's not a duplicate, update metadata to be unique and resend
AMOUNT_ZEROThe payout was recorded with an amount of $0.00A new payout with unique external_id will need to be created to retry with a non-zero amount. Log for potential system errors.

Failed Disbursements

If the status of a disbursement is FAILED, the reason_code will contain an error cause that must be handled before expecting successful disbursement.

Reason CodeDescriptionSuggested Action
WORKER_NOT_FOUNDThe worker was not found on the active roster.Double check the worker ID to make sure that the worker ID has had a wallet or card successfully created.
PAYMENT_PROFILE_NOT_FOUNDNo destination account could be found for the provided worker.Pay user via non-Branch payment mechanism and/or prompt them to finish set up for Direct/Wallet
PAYMENT_PROFILE_SUSPENDEDThe destination account is not payable due to suspension.Worker needs to fix their account then org can retry disbursement.
PAYMENT_PROFILE_NOT_ACTIVEThe destination account is not payable because it is closed or otherwise inactive.Stop sending disbursements for this worker. Direct user to account for details or to request reopening.
PAYMENT_PROFILE_FRAUDULENTThe destination account is not payable because it has been closed for fraud.User’s account is not payable due to fraud. Pay user via non-Branch payment mechanism.
TRANSFER_FAILEDAn error occurred while issuing the funds to the worker.Retry won’t work. Reach out to Support or your Account Manager for details
AMOUNT_EXCEEDS_ORG_
SINGLE_DISBURSEMENT_LIMIT
The amount exceeds the organization's limit for a single disbursement.If payment amount is correct, reach out to Support or your Account Manager to adjust the payout limit configuration
AMOUNT_EXCEEDS_ORG_
DAILY_DISBURSEMENT_LIMIT
The amount would exceed the organization's daily limit for disbursements.Wait 24 hours to send additional payouts or reach out to Support or your Account Manager to review org daily limit
AMOUNT_EXCEEDS_WORKER_
DAILY_DISBURSEMENT_LIMIT
The amount would exceed the worker's daily limit for disbursements.Wait 24 hours to send additional payouts or reach out to Support or your Account Manager to review worker payout limit
AMOUNT_DOES_NOT_
COVER_USER_FEES
The fee to be charged to the worker exceeds or is equal to the disbursement amount.Allow additional funds to accumulate before sending payout so that it exceeds minimum user-paid fee
UNEXPECTED_ERRORSomething unexpected occurred. Contact Branch support if this persists.Retry the payout. If the problem persists reach out to Support or your Account Manager

Retry a Disbursement

Before retrying a disbursement, first confirm that the status = FAILED or CANCELED. If status = COMPLETED, SKIPPED, SCHEDULED, or PENDING, the request will act as an idempotent GET.

To retry an existing disbursement, set retry = true, and set external_id and type to match the original request. This method is more resilient to temporary states and intermittent failures, as it will never result in accidental overpayment.

Alternatively, initiate a new disbursement using a different external_id. If temporary failure states aren't detected and handled correctly while using this method, duplicate payments could occur.