Standard Disbursements Flow

API Reference — Standard Disbursements Flow

The Standard Disbursements Flow stores the recipient and their debit card with Green Dot, so you can
pay them again without re-collecting their details. You create a recipient profile, link the card
they want to be paid to, and then send transfers to that card for as long as the relationship
lasts.

Every call in this flow returns its result in the response, and no webhooks are generated.

The flow

All paths are relative to {baseUrl}/programs/{programCode}.

%%{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

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

    rect rgba(0, 165, 80, 0.08)
        Note over P,GD: Once per recipient
        P->>GD: Step 1 · POST /externalAccounts/customers
        GD-->>P: 201 Created · customerToken
        P->>GD: Step 2 · POST /externalAccounts/customers/{customerToken}/cards
        GD-->>P: 201 Created · link.linkId
    end

    rect rgba(30, 110, 200, 0.08)
        Note over P,GD: Every payout
        P->>GD: Step 3 · POST /transfers (target = card link ID)
        alt Processed
            GD-->>P: 201 Created · transferStatus
        else Downstream timeout
            GD-->>P: 202 Accepted · Pending, Green Dot retries for up to 24 hours
        end
    end

Steps 1 and 2 run once per recipient and card. Step 3 runs once per payout. Each step hands the
next one the identifier it needs:

StepCallReturnsUsed in
1Create a recipient profilecustomerTokenStep 2 path parameter
2Link the recipient's debit cardlink.linkId (card link ID)Step 3 targetTransferEndpoint.identifier
3Send the disbursementtransfer.transferStatusYour payout records

Steps 1 and 2 run once per recipient and card. Step 3 runs once per payout. Each step hands the
next one the identifier it needs:

StepReturnsUsed in
1 — Create recipient profilecustomerTokenStep 2 path parameter
2 — Link the cardlink.linkId (the card link ID)Step 3 targetTransferEndpoint.identifier
3 — Send the disbursementtransfer.transferStatusYour records

Before you start, make sure you have your program code, disbursement account identifier, access
token, and program public certificate. See Before You Begin.

A note on vocabulary. The API calls the person you are paying a customer, and the object
that represents them a customer profile. Throughout these guides they are the same thing as
your recipient.


Step 1 — Create a recipient profile

Creates the record that represents the person you are paying. The recipient's details go through
Green Dot's verification process, including OFAC screening, before they can be paid.

When to call it: Once per recipient, the first time you need to pay them. The profile persists;
do not create it again for the same person.

Syntax

POST {baseUrl}/programs/{programCode}/externalAccounts/customers

Request

POST {baseUrl}/programs/{programCode}/externalAccounts/customers HTTP/1.1
Authorization: Bearer {accessToken}
X-GD-RequestId: a0b1c2d3-e4f5-6789-abcd-ef0123456789
X-GD-CustomerType: external
Content-Type: application/json
Accept: application/json

{
  "salt": "a0b1c2d3-e4f5-6789-abcd-ef0123456789",
  "customerToken": "",
  "encryptedData": {
    "version": "EC_v1",
    "ephemeralPublicKey": "BFz9k2Qc1XvR7mNp3JhTgWq8sYd4LbCe6AoUi0PxZrK=",
    "publicKeyHash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
    "data": "eyJmaXJzdE5hbWUiOiJBbGV4IiwibGFzdE5hbWUiOiJKb2huc29uIn0="
  }
}

Encrypted payload (before encryption)

{
  "firstName": "Alex",
  "lastName": "Johnson",
  "middleName": "",
  "email": "[email protected]",
  "phoneNumber": "5550123456",
  "dateOfBirth": "1988-04-12",
  "address": {
    "addressLine1": "123 Main Street",
    "addressLine2": "",
    "city": "Springfield",
    "state": "IL",
    "zipcode": "62701"
  }
}

The required set of identity fields varies by program and use case. Your program onboarding
documentation specifies exactly what your program requires.

Request parameters

ParameterRequiredTypePatternDescription
programCodeYesStringPath parameterThe program code assigned to you at onboarding.
X-GD-RequestIdYesUUIDGUIDPassed as an HTTP header. Unique per request.
X-GD-CustomerTypeNoStringDefaults to externalPassed as an HTTP header. Leave at the default.
saltYesUUIDGUIDMust match the X-GD-RequestId header value. Used for idempotency and encryption.
customerTokenConditionalStringMax 50Leave empty to have Green Dot generate a token. Send your own unique value if your program is configured to supply one — some programs require it.
encryptedDataYesObject—The recipient's identity details, encrypted with your program's public certificate.

Response

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

{
  "customerToken": "b1c2d3e4-f5a6-7890-bcde-f01234567890",
  "status": "Pending",
  "responseDetails": [
    {
      "code": 0,
      "subCode": 0,
      "description": "Success"
    }
  ]
}

Response parameters

ParameterTypeDescription
customerTokenStringThe identifier for this recipient profile. Store it. It is the path parameter for Step 2 and for retrieving this recipient's transfers.
statusStringThe profile's status. A new profile starts as Pending.
responseDetailsArrayStatus code, sub-code, and description. code: 0 means success.

Response codes

CodeDescriptionExplanation
201CreatedThe recipient profile was created.
400Invalid or missing parametersA required field is missing or malformed. Check the responseDetails sub-code.
401UnauthorizedToken missing, expired, or out of scope. Request a new token and retry.
403ForbiddenYour program is not authorized for this operation.
500Internal Server ErrorRetry the request. See the note on duplicate profiles below.
503Service UnavailableRetry the request. See the note on duplicate profiles below.

Duplicate profiles. The duplicate check is based on customerToken. If you supply a token that
already exists, the request is rejected with a "record already exists" error rather than creating
a second profile. If you leave customerToken empty, Green Dot generates a new token on every
request, so a retry after a timeout can create a second profile. Supply your own tokens, derived
from your system of record, where your program allows it.


Step 2 — Link the recipient's debit card

Links the debit card the recipient wants to be paid to, and returns the card link ID you send
payouts to. Green Dot checks that the card's BIN is eligible for fast-funds push payments through
the card networks.

When to call it: Once per card, after the recipient profile exists. A recipient can have more
than one card linked. Call it again only to link a different card.

Syntax

POST {baseUrl}/programs/{programCode}/externalAccounts/customers/{customerToken}/cards

Request

POST {baseUrl}/programs/{programCode}/externalAccounts/customers/b1c2d3e4-f5a6-7890-bcde-f01234567890/cards HTTP/1.1
Authorization: Bearer {accessToken}
X-GD-RequestId: c2d3e4f5-a6b7-8901-cdef-012345678901
X-GD-CustomerType: external
Content-Type: application/json
Accept: application/json

{
  "salt": "c2d3e4f5-a6b7-8901-cdef-012345678901",
  "encryptedData": {
    "version": "EC_v1",
    "ephemeralPublicKey": "BFz9k2Qc1XvR7mNp3JhTgWq8sYd4LbCe6AoUi0PxZrK=",
    "publicKeyHash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
    "data": "eyJhY2NvdW50TnVtYmVyIjoiNDExMTExMTExMTExMTIzNCJ9"
  }
}

Encrypted payload (before encryption)

{
  "firstName": "Alex",
  "lastName": "Johnson",
  "middleName": "",
  "nickName": "Payout card",
  "accountNumber": "4111111111111234",
  "expiryMonth": "12",
  "expiryYear": "2029",
  "address": {
    "addressLine1": "123 Main Street",
    "addressLine2": "",
    "city": "Springfield",
    "state": "IL",
    "zipCode": "62701"
  }
}

Card number, expiration, cardholder name, and billing address all travel inside the encrypted
payload. Nothing card-related is sent in plain text.

Request parameters

ParameterRequiredTypePatternDescription
programCodeYesStringPath parameterThe program code assigned to you at onboarding.
customerTokenYesStringPath parameterThe customerToken returned in Step 1.
X-GD-RequestIdYesUUIDGUIDPassed as an HTTP header. Unique per request.
X-GD-CustomerTypeNoStringDefaults to externalPassed as an HTTP header. Leave at the default.
saltYesUUIDGUIDMust match the X-GD-RequestId header value.
encryptedDataYesObject—The card and cardholder details below, encrypted with your program's public certificate.

Encrypted payload fields

FieldRequiredTypeDescription
accountNumberYesStringThe debit card number.
expiryMonthYesStringExpiration month, MM.
expiryYearYesStringExpiration year, YYYY.
firstNameYesStringCardholder's first name, as it appears on the account.
lastNameYesStringCardholder's last name, as it appears on the account.
middleNameNoStringCardholder's middle name.
nickNameNoStringA label for the card, useful when a recipient has more than one.
addressYesObjectCardholder billing address: addressLine1, addressLine2, city, state (2 characters), zipCode (5 digits).

Response

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

{
  "link": {
    "linkId": "d3e4f5a6-b7c8-9012-def0-123456789012"
  },
  "responseDetails": [
    {
      "code": 0,
      "subCode": 0,
      "description": "Success"
    }
  ]
}

Response parameters

ParameterTypeDescription
link.linkIdUUIDThe card link ID. Store it against your record of the recipient. It is the destination identifier for every payout to this card.
responseDetailsArrayStatus code, sub-code, and description. code: 0 means success.

Response codes

CodeDescriptionExplanation
201CreatedThe card was linked.
400Invalid or missing parametersA required field is missing or malformed. Check the sub-code.
401UnauthorizedToken missing, expired, or out of scope. Request a new token and retry.
403ForbiddenYour program is not authorized for this operation.
404Not FoundThe recipient profile for this customerToken was not found.
500Internal Server ErrorRetry the request. Linking the same card again returns the existing link.
503Service UnavailableRetry the request. Linking the same card again returns the existing link.

How card links behave

  • Linking is idempotent. Linking a card that is already linked to the same recipient returns
    the existing card link instead of creating a new one.
  • Link status changes after the first payout. A new card link starts as InActive and becomes
    Active after the first successful transfer to it. An InActive link can still receive a
    payout.
  • Expiration is validated when the card is linked.

Step 3 — Send the disbursement

Moves money from your disbursement business account to the recipient's linked card.

When to call it: Every time you pay the recipient. In steady state, this is the only call you
make.

Syntax

POST {baseUrl}/programs/{programCode}/transfers

Request

POST {baseUrl}/programs/{programCode}/transfers HTTP/1.1
Authorization: Bearer {accessToken}
X-GD-RequestId: e4f5a6b7-c8d9-0123-ef01-234567890123
Content-Type: application/json
Accept: application/json

{
  "transferIdentifier": "f5a6b7c8-d9e0-1234-f012-345678901234",
  "transferType": "DisbursementExternal",
  "transferAuthorizationType": "execute",
  "initiator": "0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
  "partnerReferenceData": "PAYRUN-20260115-0042",
  "transferRoute": {
    "transactionAmount": 100.00,
    "transactionDescription": "Weekly payout",
    "sourceTransferEndpoint": {
      "transferEndPointType": "programFundingSource",
      "identifier": "0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
      "currency": "USD"
    },
    "targetTransferEndpoint": {
      "transferEndPointType": "card",
      "identifier": "d3e4f5a6-b7c8-9012-def0-123456789012",
      "currency": "USD"
    }
  }
}

The source is your disbursement business account. The target is the card link ID from Step 2.

Request parameters

ParameterRequiredTypePatternDescription
programCodeYesStringPath parameterThe program code assigned to you at onboarding.
X-GD-RequestIdYesUUIDGUIDPassed as an HTTP header. Unique per request.
transferIdentifierYesUUIDGUIDYour unique identifier for this payout. Reuse it on retries; never reuse it across payouts.
transferTypeYesStringDisbursementExternalUse DisbursementExternal for a disbursement.
transferAuthorizationTypeYesStringexecuteMust be execute. Disbursements are single-phase; there is no separate authorize step.
initiatorNoString36 charactersYour disbursement account identifier. Optional; if supplied, it must match the source.
partnerReferenceDataNoStringSee note belowYour own reference for this payout. Can be included in settlement reporting on request, which makes reconciliation against your records straightforward.
transferRouteYesObject—Amount, source, and destination for the payout.
transferRoute.transactionAmountYesDecimale.g. 100.00The amount to send.
transferRoute.transactionDescriptionNoStringMax 250Description carried with the transaction.
sourceTransferEndpoint.transferEndPointTypeYesStringprogramFundingSourceUse programFundingSource.
sourceTransferEndpoint.identifierYesString36 charactersYour disbursement account identifier, issued at onboarding.
sourceTransferEndpoint.currencyNoString3-character ISODefaults to USD. Only USD is supported.
targetTransferEndpoint.transferEndPointTypeYesStringcardUse card for a payout to a linked debit card.
targetTransferEndpoint.identifierYesUUIDGUIDThe card link ID (link.linkId) returned in Step 2.
targetTransferEndpoint.currencyNoString3-character ISODefaults to USD. Only USD is supported.
fraudDataNoObjectKey/value pairsAdditional fraud signals for this payout.
deviceDetailsNoObject—Device type, device token, and IP address of the device that triggered the payout. Recommended when the recipient initiated the request.

partnerReferenceData accepts printable ASCII characters except comma (,), semicolon (;),
backtick (`), and pipe (|).

Response

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

{
  "transfer": {
    "transferIdentifier": "f5a6b7c8-d9e0-1234-f012-345678901234",
    "transferStatus": "Completed"
  },
  "responseDetails": [
    {
      "code": 0,
      "subCode": 0,
      "description": "Success"
    }
  ]
}

Response parameters

ParameterTypeDescription
transfer.transferIdentifierStringThe identifier for this payout — the same value you sent.
transfer.transferStatusStringThe status of the payout. See Transfer Status & Webhooks.
responseDetailsArrayStatus code, sub-code, and description. code: 0 means success.

Error response

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

[
  {
    "code": 4200,
    "subCode": 940,
    "description": "Invalid Transaction Amount"
  }
]

Response codes

CodeDescriptionExplanation
201CreatedThe payout was processed. Read transferStatus for the outcome.
202AcceptedA downstream timeout occurred. The payout is Pending while Green Dot retries automatically. See When a payout is pending.
400Bad RequestValidation failed. The body identifies the field.
401UnauthorizedToken missing, expired, or out of scope. Request a new token and retry.
403ForbiddenYour program is not authorized for this transfer type.
404Not FoundThe program, disbursement account, or card link could not be found.
500Internal Server ErrorRetry with the same transferIdentifier.
503Service UnavailableRetry with the same transferIdentifier.

See [Response Codes](./08-response-codes.md) for the full sub-code reference.


Tracking payouts

Because this flow is synchronous, the transfer response tells you the outcome directly in most
cases. For reconciliation, support questions, and any payout that returned Pending, retrieve the
transfer by customer token and transfer identifier.

See the External Accounts API reference for Retrieve a transfer by customer token and
transfer ID
and Search transfers by date range for a customer profile.

Managing recipients and cards

The External Accounts API group also lets you maintain what you have stored:

To do thisUse
Update a recipient's detailsUpdate an existing customer profile
Retrieve a recipient's detailsRetrieve a customer profile
Update a linked cardUpdate a card link for a customer profile
Remove a card the recipient no longer wants to useDelete a card link from a customer profile

A deleted card link cannot be used for new payouts.

Paying the same recipient again

Once Steps 1 and 2 are done, every future payout is Step 3 on its own. Store customerToken and
the card link ID against your own record of the person, and reuse them. Do not recreate the profile
or relink the card.

Paying many recipients

Payouts are initiated one at a time. To run a payout batch, iterate your list and call Step 3 once
per recipient, generating a fresh transferIdentifier for each. Track each payout independently —
one failure in a run does not affect the others, and each needs its own resolution.

Before a large run, confirm your disbursement account holds enough funds to cover the whole batch.


Did this page help you?