Single Call Disbursements Flow (Async)

API Reference — Single Call Disbursement Flow (Async)

The Single Call Disbursements Flow (Async) sends a payout in one request. Recipient details, card
details, and the amount travel together, and the final outcome is delivered asynchronously to your
webhook endpoint.

Nothing is stored for reuse: each payout carries everything it needs. That fits programs where
recipients are paid once or occasionally and there is no ongoing relationship to maintain.

The flow

%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Arial, Helvetica, sans-serif", "fontSize": "15px", "actorBkg": "#00A550", "actorBorder": "#00A550", "actorTextColor": "#FFFFFF", "actorLineColor": "#B0B0B0", "signalColor": "#404040", "signalTextColor": "#404040", "noteBkgColor": "#F5F5F5", "noteBorderColor": "#C8C8C8", "noteTextColor": "#404040", "labelBoxBkgColor": "#FFFFFF", "labelBoxBorderColor": "#9E9E9E", "labelTextColor": "#404040", "loopTextColor": "#404040"}, "sequence": {"mirrorActors": false, "messageAlign": "center"}}}%%
sequenceDiagram
    participant P as Your platform
    participant GD as Green Dot API
    participant W as Your webhook endpoint

    Note over P,W: Before you begin — program setup, account funding, and webhook registration (no API call)

    rect rgba(0, 165, 80, 0.08)
        Note over P,GD: Every payout
        P->>GD: Step 1 · POST /enrollment/v1/api/flex/transfers/singlecommit
        Note right of P: Recipient details, encrypted card data, and amount in one request
        GD-->>P: 201 Created · transferStatus Pending
    end

    rect rgba(30, 110, 200, 0.08)
        Note over GD,W: Asynchronous outcome
        GD->>W: Step 2 · POST /events/SinglePhaseTransfer
        Note right of GD: Completed, Failed, or Declined
        W-->>GD: Acknowledge receipt
    end

    opt Webhook missed or delayed
        P->>GD: GET /enrollment/v1/api/flex/externalAccounts/{externalAccountId}/transfers/{transferId}
        GD-->>P: Current transferStatus
    end
StepWhat happensWhat you receive
1You send the payout in a single request201 Created with transferStatus: Pending
2Green Dot delivers the final outcome to your webhook endpointCompleted, Failed, or Declined
FallbackYou look up the payout if a webhook is missedThe current transferStatus

Before you start, make sure you have your disbursement account identifier, payee site identifier,
access token, program public certificate, and a webhook endpoint that is deployed and reachable.
See Before You Begin.

This flow requires a webhook endpoint. The 201 response confirms the request was accepted,
not that the money arrived. The webhook is how you learn the final outcome, including declines.


Step 1 — Send the disbursement

Creates and executes a payout to a debit card in one call.

When to call it: Once per payout. There is no setup call and no prior state.

Syntax

POST {baseUrl}/enrollment/v1/api/flex/transfers/singlecommit

Environment base URLs are issued during onboarding.

Request

POST {baseUrl}/enrollment/v1/api/flex/transfers/singlecommit HTTP/1.1
x-Remapped-Authorization: Bearer {accessToken}
Request-ID: 1a2b3c4d-5e6f-7081-92a3-b4c5d6e7f809
Content-Type: application/json

{
  "transferIdentifier": "2b3c4d5e-6f70-8192-a3b4-c5d6e7f80912",
  "transferType": "DisbursementExternal",
  "initiator": "0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
  "transferdescription": "Settlement payment",
  "transferRoute": {
    "transactionAmount": 20.00,
    "sourceTransferEndpoint": {
      "transferEndPointType": "programFundingSource",
      "identifier": "0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
      "currency": "USD"
    },
    "targetTransferEndpoint": {
      "transferEndPointType": "singlePhaseFunding",
      "identifier": "3c4d5e6f-7081-92a3-b4c5-d6e7f8091234",
      "currency": "USD",
      "encryptedCardData": {
        "version": "EC_v1",
        "ephemeralPublicKey": "BFz9k2Qc1XvR7mNp3JhTgWq8sYd4LbCe6AoUi0PxZrK=",
        "publicKeyHash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
        "data": "eyJjYXJkTnVtYmVyIjoiNDExMTExMTExMTExMTIzNCJ9"
      },
      "encryptedUserData": {
        "version": "EC_v1",
        "ephemeralPublicKey": "BFz9k2Qc1XvR7mNp3JhTgWq8sYd4LbCe6AoUi0PxZrK=",
        "publicKeyHash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
        "data": "eyJmaXJzdE5hbWUiOiJBbGV4IiwibGFzdE5hbWUiOiJKb2huc29uIn0="
      }
    }
  }
}

Request headers

HeaderRequiredTypePatternDescription
x-Remapped-AuthorizationYesStringBearer {accessToken}Your OAuth 2.0 access token. This endpoint reads the token from this header rather than Authorization.
Request-IDYesUUIDGUIDUnique per request.
Content-TypeYesStringapplication/json—

Request parameters

ParameterRequiredTypePatternDescription
transferIdentifierYesUUIDGUIDYour unique identifier for this payout. Reuse it on retries; never reuse it across payouts.
transferTypeYesStringDisbursementExternalUse DisbursementExternal.
initiatorNoString36 charactersThe account the payout is initiated from. Optional in this flow; if supplied, it must be the source or the target.
transferdescriptionNoStringMax 100A description of the payout. Note the field name is all lowercase in this endpoint.
transferRoute.transactionAmountYesDecimale.g. 20.00The amount to send.
sourceTransferEndpoint.transferEndPointTypeYesStringprogramFundingSourceUse programFundingSource.
sourceTransferEndpoint.identifierYesString36 charactersYour disbursement account identifier, issued at onboarding.
sourceTransferEndpoint.currencyYesString3-character ISOOnly USD is supported.
targetTransferEndpoint.transferEndPointTypeYesStringsinglePhaseFundingUse singlePhaseFunding for this flow.
targetTransferEndpoint.identifierYesUUIDGUIDYour payee site identifier, issued at onboarding.
targetTransferEndpoint.currencyYesString3-character ISOOnly USD is supported.
targetTransferEndpoint.encryptedCardDataYesObject—The recipient's card details, encrypted. Fields below.
targetTransferEndpoint.encryptedUserDataYesObject—The recipient's identity details, encrypted. Fields below.

Card data fields (encrypted)

These are the fields inside the encrypted encryptedCardData payload.

FieldRequiredTypePatternDescription
cardNumberYesStringDigits onlyThe recipient's debit card number.
expirationYesStringMMYYYYCard expiration date.
cvvNoString3–4 digitsCard security code.
firstNameYesString2–35 characters; letters, hyphen, spaceCardholder's first name.
lastNameYesString2–35 characters; letters, hyphen, spaceCardholder's last name.
address1YesStringMax 255Cardholder address, line 1.
address2NoStringMax 255Cardholder address, line 2.
cityYesStringMax 50; letters, hyphen, spaceCardholder city.
stateYesString2 charactersCardholder state.
zipCodeYesString5 digitsCardholder ZIP code.

User data fields (encrypted)

These are the fields inside the encrypted encryptedUserData payload.

FieldRequiredTypePatternDescription
firstNameYesString2–35 characters; letters, hyphen, spaceRecipient's first name.
lastNameYesString2–35 characters; letters, hyphen, spaceRecipient's last name.
zipCodeYesString5 digitsRecipient's ZIP code.
dateOfBirthConditionalStringYYYY-MM-DDRequired for some program configurations. Year must be between 1901 and the current year.

Response — accepted

HTTP/1.1 201 Created
Content-Type: application/json

{
  "transfer": {
    "transferIdentifier": "2b3c4d5e-6f70-8192-a3b4-c5d6e7f80912",
    "transferStatus": "Pending"
  }
}

Response parameters

ParameterTypeDescription
transfer.transferIdentifierStringThe identifier for this payout — the same value you sent.
transfer.transferStatusStringThe status when the response was sent. Typically Pending; the final state arrives by webhook.
errorsArrayPresent only on failure. Contains code, subcode, and description.

Response — validation failure

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "transfer": {
    "transferIdentifier": "2b3c4d5e-6f70-8192-a3b4-c5d6e7f80912",
    "transferStatus": "failed"
  },
  "errors": [
    {
      "code": 4200,
      "subcode": 945,
      "description": "Invalid Request Id"
    }
  ]
}

Response — system error

HTTP/1.1 503 Service Unavailable
Content-Type: application/json

{
  "transfer": {
    "transferIdentifier": "2b3c4d5e-6f70-8192-a3b4-c5d6e7f80912",
    "transferStatus": "failed"
  },
  "errors": [
    {
      "code": 4214,
      "subcode": 1514,
      "description": "system error"
    }
  ]
}

A 503 means a timeout or internal error. It does not necessarily mean that no money moved. Retry with the
same transferIdentifier — the platform returns the existing record rather than sending a
second payment.

Response codes

CodeDescriptionExplanation
201CreatedThe payout was accepted. Wait for the webhook for the final outcome.
200Record already existsResponse code 4202, sub-code 1502. You resubmitted a transferIdentifier that already exists; the existing transfer's status is returned.
400Validation failedA field is missing or malformed. The sub-code identifies which.
401UnauthorizedToken missing, expired, or out of scope. Request a new token and retry.
503System errorTimeout or internal error. Retry with the same transferIdentifier.

See Response Codes for the full sub-code reference.


Step 2 — Receive the outcome

Green Dot posts the final result of the payout to the endpoint you registered during onboarding.

POST https://{yourEndpoint}/events/SinglePhaseTransfer

Webhook payload

{
  "accounts": [
    {
      "accountIdentifier": "4d5e6f70-8192-a3b4-c5d6-e7f809123456",
      "events": [
        {
          "eventIdentifier": "5e6f7081-92a3-b4c5-d6e7-f80912345678",
          "eventType": "singlePhaseTransfer",
          "eventDateTime": "2026-01-15T12:00:07.1411753Z",
          "singlePhaseTransfer": [
            {
              "transferIdentifier": "2b3c4d5e-6f70-8192-a3b4-c5d6e7f80912",
              "transactionAmount": 20.00,
              "transferStatus": "Completed",
              "transferDateTime": "2026-01-15T12:00:07Z",
              "response": {
                "code": "0",
                "subCode": "0",
                "description": "success"
              }
            }
          ]
        }
      ]
    }
  ]
}

Webhook fields

FieldTypeDescription
accounts[].accountIdentifierUUIDThe account the event relates to.
events[].eventIdentifierUUIDUnique identifier for this event delivery. Use it to deduplicate.
events[].eventTypeStringsinglePhaseTransfer for this flow.
events[].eventDateTimeDateTimeWhen the event was generated.
singlePhaseTransfer[].transferIdentifierStringMatches the transferIdentifier you sent. This is how you tie the webhook to your record.
singlePhaseTransfer[].transactionAmountDecimalThe payout amount.
singlePhaseTransfer[].transferStatusStringCompleted, Failed, or Declined.
singlePhaseTransfer[].transferDateTimeDateTimeWhen the payout reached this status.
singlePhaseTransfer[].responseObjectcode, subCode, and description explaining the outcome.

Statuses you will receive

StatusMeaningWhat to do
CompletedThe payout succeeded and funds reached the recipient.Mark the payout complete.
FailedA system error occurred.Investigate the sub-code, then send a new payout with a new transferIdentifier.
DeclinedThe payout was refused — ineligible account, limit exceeded, OFAC, or below the minimum amount.Do not retry blindly. Resolve the underlying reason first; the sub-code tells you which.

See Transfer Status & Webhooks for handling guidance.

Handling webhooks well

  • Respond fast. Acknowledge the delivery, then process asynchronously.
  • Deduplicate on eventIdentifier. Assume a webhook can arrive more than once.
  • Match on transferIdentifier, not amount or timestamp. It is the only reliable key.
  • Do not assume ordering. Treat each event on its own merits.
  • Have a fallback. If your endpoint is down, use the status lookup below.

Looking up a payout

Retrieve a payout's current state at any time, whether or not the webhook arrived.

Syntax

GET {baseUrl}/enrollment/v1/api/flex/externalAccounts/{externalAccountId}/transfers/{transferId}

Request parameters

ParameterRequiredTypePatternDescription
externalAccountIdYesUUIDGUIDPath parameter. Your payee site identifier.
transferIdYesUUIDGUIDPath parameter. The transferIdentifier of the payout.
x-Remapped-AuthorizationYesStringBearer {accessToken}Passed as an HTTP header.
Request-IDYesUUIDGUIDPassed as an HTTP header. Unique per request.

Response

HTTP/1.1 200 OK
Content-Type: application/json

{
  "transfer": {
    "transferId": "2b3c4d5e-6f70-8192-a3b4-c5d6e7f80912",
    "transferStatus": "Completed",
    "currency": "USD",
    "transactionAmount": "20.00",
    "totalFeeAmount": "0.0",
    "totalTransactionAmount": "20.00"
  }
}

Response parameters

ParameterTypeDescription
transferIdStringThe payout identifier.
transferStatusStringCurrent status.
currencyStringCurrency of the payout.
transactionAmountStringThe amount sent to the recipient.
totalFeeAmountStringFees applied to the payout.
totalTransactionAmountStringAmount plus fees.

Paying many recipients

Each payout is its own call with its own transferIdentifier. To run a batch, iterate your list
and submit one request per recipient. Because outcomes arrive asynchronously, a batch is finished
when every payout has reached a final status, not when the loop finishes.

Reconcile on a schedule: any payout still Pending well past its expected settlement window should
be looked up directly rather than waited on.


Did this page help you?