Payment Orders

A payment_order is an instruction to move money to or from your account via payment types such as ACH, wire, RTP, stablecoin, and check. The payment order includes statuses that update you over the lifecycle of the payment.

Related Guides:

AttributeDescription
id stringUnique identifier for the payment order
external_id stringAn optional user-defined 180 character unique identifier
type string

One of ach(US ACH)

book(Book)

check (Check)

rtp (Real Time Payment and FedNow)

stablecoin (onchain transfer in USDG, USDC, PYUSD, USDT, etc)

wire (Domestic Wires)

card (Push to Card)

subtype string

An additional layer of classification for the type of payment order you are doing. This field is only used for ach and stablecoin payment orders currently.

For ach payment orders, the subtype represents the SEC code. We currently support CCD, PPD, CTX, WEB, and TEL.

For stablecoin, pass in the intended blockchain network. See here for a list supported networks.

amount int64

Value in specified currency's smallest unit. e.g. $10 (US Dollar) would be represented as 1000. For stablecoins (USDC, USDG, USDT, PYUSD), the smallest unit is 6 decimal places — e.g. $10 USDC would be represented as 10000000.

For RTP, the maximum amount allowed by the network is $10,000,000.

currency stringMust conform to ISO 4217. Defaults to the currency of the originating account.
direction string

One of credit, debit

Describes the direction money is flowing in the transaction. A credit moves money from your account to someone else's. A debit pulls money from someone else's account to your own.

Note that rtp and check payments will always be credit.

status stringThe current status of the payment order. See the status section for details.
reconciliation_status stringThe current reconciliation status. One of unreconciled, tenatively_reconciled, or reconciled.
priority string

Either normal or high.

high priority is only available for ach and check payment types.

For ACH payments, high represents a same-day transfer. For check payments, high can mean an overnight check rather than standard mail. For all other payment types, high priority payments are treated the same as normal priority payments.

originating_account_id stringThe ID of one of your organization's internal accounts
receiving_account_id stringThe receiving account ID. Can be an external account or internal account
receiving_account_type stringThe receiving account type. Can be one of external_account or internal_account.
description stringAn optional description for internal use.
effective_date date

Date transactions are to be posted to the participants' account. Defaults to the current business day or the next business day if the current day is a bank holiday or weekend.

Format: yyyy-mm-dd

process_after string

If present, Modern Treasury will not process the payment until after this time. If process_after is past the cutoff for effective_date, process_after will take precedence and effective_date will automatically update to reflect the earliest possible sending date after process_after.

Format: ISO8601 timestamp

statement_descriptor stringAn optional descriptor which will appear in the receiver's statement. For check payments this field will be used as the memo line. For ach the maximum length is 10 characters. Note that for ACH payments, the name on your bank account will be included automatically by the bank, so you can use the characters for other useful information.
remittance_information string

For ach, this field will be passed through on an addenda record. For wire payments the field will be passed through as the "Originator to Beneficiary Information", also known as OBI or Fedwire tag 6000.

Character limits vary by bank and rail. Typical limits are 80 characters for ach payments, and 140 characters for wire payments.

purpose stringFor wire, this is usually the purpose which is transmitted via the "InstrForDbtrAgt" field in the ISO20022 file.
metadata objectAdditional data represented as key-value pairs. Both the key and value must be strings. See Metadata.
counterparty_id stringIf the payment order is tied to a specific Counterparty , their id will appear, otherwise null.
transaction_ids arrayThe IDs of all the transactions associated to this payment order. Usually, you will only have a single transaction ID. However, if a payment order initially results in a Return, but gets redrafted and is later successfully completed, it can have many transactions.
current_return objectIf the payment order's status is returned, this will include the return object's data.
current_hold objectIf the payment order's status is held, this will include the Hold object's data.
originating_party_name stringIf present, this will replace your default company name on receiver's bank statement. For ACH, only the first 16 characters of this string will be used. This must be a name the account holder legally operates under, such as a DBA. Do not use it to originate on behalf of another person or business, including an end customer.
originating_party_address objectThe address of the originating party. If present, this overwrites the party_address on the payment order. Accepts an address object with line1, line2, locality, region, postal_code, and country.
nsf_protected
boolean
  • Default:* false
A boolean to determine if NSF Protection is enabled for this payment order. NSF Protection is a feature that only works for external accounts that are created with Plaid processor tokens. Also note that you must turn on the setting for this feature in your organization settings page.
expires_at
datetime
For check payment orders, the date after which the check is considered void. Must be within 180 days of the effective_date. For rtp payment orders, the datetime that a Request for Payment expires. null for other payment types.
live_mode booleanThis field will be true if this object was created with a production API key or false if created with a test API key.
reference_numbers arrayAn array of Payment Reference objects.
ledger_transaction_id stringThe ID of the ledger transaction linked to the payment order. See Linking to other Modern Treasury objects .
{
  "id": "c5f4009c-bdd6-4cc1-84b2-17974ac9e77a",
  "external_id": null,
  "type": "ach",
  "subtype": null,
  "amount": 20000,
  "currency": "USD",
  "direction": "credit",
  "status": "approved",
  "reconciliation_status": "unreconciled",
  "priority": "normal",
  "originating_account_id": "0f8e3719-3dfd-4613-9bbf-c0333781b59f",
  "receiving_account_id": "5acec2ef-987b-4260-aa97-b719eeb0a8d5",
  "receiving_account_type": "external_account",
  "description": "Invoice #12345 payment",
  "effective_date": "2018-11-08",
  "process_after": null,
  "statement_descriptor": "Rerum del.",
  "remittance_information": "Accusamus tempore molestiae laboriosam.",
  "purpose": null,
  "metadata": {
    "invoice_id": "INV-12345",
    "customer_ref": "CUST-789"
  },
  "counterparty_id": "37ba4454-dd33-4aa0-8906-0e2e4103e45c",
  "transaction_ids": [],
  "current_return": null,
  "current_hold": null,
  "nsf_protected": false,
  "originating_party_name": "Acme Company",
  "originating_party_address": {
    "line1": "1234 Main Street",
    "line2": "Suite 100",
    "locality": "San Francisco",
    "region": "CA",
    "postal_code": "94105",
    "country": "US"
  },
  "expires_at": null,
  "live_mode": true,
  "created_at": "2019-11-09T00:11:07Z",
  "updated_at": "2019-11-09T00:11:07Z"
}

Payment Order Statuses

The statusfield represents the current state of a payment order. Webhook events can be configured to listen for changes in state.

Legend:

flowchart LR
    state_1(["State 1"]) -->|webhook_event| state_2(["State 2"])

    classDef active fill:#1EA373,stroke:#1EA373,color:#FFFFFF

    class state_1,state_2 active
flowchart TD
    create["Create Payment Order in App or API"]

    needs_approval(["Needs Approval ²"])
    denied(["Denied"])
    cancelled(["Cancelled"])
    approved(["Approved"])
    processing(["Processing"])
    sent(["Sent"])
    stopped(["Stopped ⁴"])
    failed(["Failed ³"])
    completed(["Completed ⁵"])
    returned(["Returned ⁶"])
    reversed(["Reversed"])

    create -->|created ¹| needs_approval
    needs_approval -->|denied| denied
    needs_approval -->|cancelled| cancelled
    needs_approval -->|approved| approved
    approved -->|cancelled| cancelled
    approved -->|begin_processing| processing
    processing -->|finish_processing| sent
    sent -->|stopped| stopped
    sent -->|completed| completed
    sent -->|returned| returned
    sent -->|reversed| reversed
    sent -->|failed| failed
    completed -->|returned| returned
    completed -->|reversed| reversed
    create -->|failed ¹| failed
    failed -->|redrafted| needs_approval
    returned -->|redrafted| needs_approval

    reversed ~~~ returned

    classDef entry fill:#2B71D4,stroke:#2B71D4,color:#FFFFFF
    classDef active fill:#1EA373,stroke:#1EA373,color:#FFFFFF
    classDef terminal fill:#CD3640,stroke:#CD3640,color:#FFFFFF

    class create entry
    class needs_approval,approved,processing,sent,completed,reversed active
    class denied,cancelled,failed,stopped,returned terminal
  1. The created and failed events are only emitted during creation when using the asynchronous API. Synchronous calls will return an HTTP code (201, 4xx) on success or failure.
  2. If there are no Approval Rules triggered, a Payment Order will go straight from Needs Approval to Approved.
  3. Once Sent, a payment may move to Failed from any state if the originating bank sends us a failure notification. When processing webhooks or polling for payment statuses, make sure you account for these edge cases.
  4. Stopped is only relevant for checks managed via Payment Actions.
  5. Completed does not imply reconciliation. Use the Reconciliation Status attribute to determine reconciliation state.
Status Description

needs_approval

The payment order needs at least one internal approval before it can be sent to the bank. If the effective_date has passed but it isn’t approved yet, it will be sent at the earliest time after approval.

approved

The payment order has been internally approved and will be sent to the bank.

denied

The payment order has been denied by an approver during internal approval.

cancelled

The payment order was cancelled before being processed.

processing

Modern Treasury is preparing the payment order to be sent for approval and execution. Once processing begins, the payment order cannot be edited or cancelled anymore.

sent

The payment order has been sent for screening and execution. Acceptance by Modern Treasury can be tracked via the payment_order.acknowledged webhook. It may remain in this state for up to a few days, depending on the type of payment order.

held

(coming soon)

The payment order has been placed on hold. The payment will not be processed further until the hold is resolved; if it is not resolved, it will be rejected and move to failed.

stopped

Check-specific: the positive pay file associated with the payment order has been revoked or cancelled.

completed

The payment order has been executed, and the transaction has been posted to the originating ledger at Modern Treasury, indicating that funds have been accepted or released.
Note: some payment order types are not final (e.g., ACH can still return later).

returned

The payment order was returned after completing. There is an associated Return object with more information.

reversed

The payment order has been reversed. There is an associated Reversal object with more information.

failed

The payment was unable to be executed. More information as to the reason may be provided on failure_reason.