Originate a check payment

Overview

Let's assume you want to send $100 via a check — for example, to pay a vendor, reimburse an employee, or issue a refund. You'll need to create a Payment Order with a Counterparty.

Before making requests, you'll need your API Key and Organization ID. Follow this guide to retrieve them: Retrieve your API Key

1. Retrieve your Internal Account ID

📘

Internal Accounts

Modern Treasury uses the term Internal Account to refer to your bank accounts. Your customers', vendors', and employees' bank accounts are called External Accounts.

When you create a payment order, you must specify which account the check will be drawn against.

To get an Internal Account ID, pick one from your accounts page.

To retrieve all internal accounts via the API, issue the following request:

curl --request GET \
  -u ORGANIZATION_ID:API_KEY \
  --url https://app.moderntreasury.com/api/internal_accounts
[
  {
    "id": "0f8e3719-3dfd-4613-9bbf-c0333781b59f",
    "object": "internal_account",
    "account_type": null,
    "party_name": "Modern Treasury",
    "party_type": null,
    "party_address": null,
    "account_details": [
      {
        "id": "aaf74f7e-d697-4a73-95a3-05bede2edce6",
        "object": "account_details",
        "account_number_safe": "2971",
        "account_number_type": null,
        "created_at": "2019-11-09T00:11:07Z",
        "updated_at": "2019-11-09T00:11:07Z"
      }
    ],
    "routing_details": [
      {
        "id": "a3649136-f8d2-46e8-8b41-327bd7da3110",
        "object": "routing_details",
        "payment_type": null,
        "routing_number": "021000021",
        "routing_number_type": "aba",
        "created_at": "2019-11-09T00:11:07Z",
        "updated_at": "2019-11-09T00:11:07Z"
      }
    ],
    "connection": {
      "id": "05487db0-e234-4ae8-914a-c627f76c987f",
      "object": "connection",
      "vendor_id": "example1",
      "vendor_name": "Gringotts Wizarding Bank",
      "created_at": "2019-11-09T00:11:07Z",
      "updated_at": "2019-11-09T00:11:07Z"
    },
    "created_at": "2019-11-09T00:11:07Z",
    "updated_at": "2019-11-09T00:11:07Z"
  }
]

The response returns an array of your Internal Accounts. For this example, use the first account ID: 0f8e3719-3dfd-4613-9bbf-c0333781b59f.

📘

Sandbox Setup

For more information on how we've set up your accounts, visit our Sandbox Details guide.

2. Create a Counterparty

When sending a check, the counterparty needs a valid mailing address for delivery. Unlike ACH or wire transfers, checks do not require a bank account number or routing number.

curl --request POST \
  -u ORGANIZATION_ID:API_KEY \
  --url https://app.moderntreasury.com/api/counterparties \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Kenner, Bach and Ledeen",
    "accounts": [
      {
        "party_address": {
          "line1": "123 Main St",
          "line2": "Suite 400",
          "locality": "San Francisco",
          "region": "CA",
          "postal_code": "94105",
          "country": "US"
        }
      }
    ]
  }'
{
  "id": "37ba4454-dd33-4aa0-8906-0e2e4103e45c",
  "object": "counterparty",
  "name": "Kenner, Bach and Ledeen",
  "email": null,
  "metadata": {},
  "accounts": [
    {
      "id": "5acec2ef-987b-4260-aa97-b719eeb0a8d5",
      "object": "external_account",
      "account_type": "other",
      "party_name": "Kenner, Bach and Ledeen",
      "party_type": null,
      "party_address": {
        "id": "f936503f-9291-42fa-ade8-e125faf89d6b",
        "object": "address",
        "live_mode": true,
        "line1": "123 Main St",
        "line2": "Suite 400",
        "locality": "San Francisco",
        "region": "CA",
        "postal_code": "94105",
        "country": "US",
        "created_at": "2019-11-09T00:11:07Z",
        "updated_at": "2019-11-09T00:11:07Z"
      },
      "account_details": [],
      "routing_details": [],
      "created_at": "2019-11-09T00:11:07Z",
      "updated_at": "2019-11-09T00:11:07Z"
    }
  ],
  "created_at": "2019-11-09T00:11:07Z",
  "updated_at": "2019-11-09T00:11:07Z"
}

The response returns a new Counterparty with one attached External Account. You'll need the External Account ID (5acec2ef-987b-4260-aa97-b719eeb0a8d5) for the next step.

3. Create a Payment Order

Create a Payment Order using your Internal Account ID as the originating_account_id and the Counterparty's External Account ID as the receiving_account_id. Set type to check and direction to credit.

curl --request POST \
  -u ORGANIZATION_ID:API_KEY \
  --url https://app.moderntreasury.com/api/payment_orders \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "check",
    "amount": 10000,
    "direction": "credit",
    "currency": "USD",
    "originating_account_id": "0f8e3719-3dfd-4613-9bbf-c0333781b59f",
    "receiving_account_id": "5acec2ef-987b-4260-aa97-b719eeb0a8d5",
    "expires_at": "2025-08-07T00:00:00Z"
  }'
📘

The expires_at field specifies when the check will no longer be honored. The default expiry for checks is 90 days from the effective_date, and the maximum expiry is 180 days from the effective_date.

{
  "id": "c5f4009c-bdd6-4cc1-84b2-17974ac9e77a",
  "object": "payment_order",
  "type": "check",
  "amount": 10000,
  "direction": "credit",
  "originating_account_id": "0f8e3719-3dfd-4613-9bbf-c0333781b59f",
  "receiving_account": {
    "id": "5acec2ef-987b-4260-aa97-b719eeb0a8d5",
    "object": "external_account",
    "account_type": "other",
    "party_name": "Kenner, Bach and Ledeen",
    "party_type": null,
    "party_address": {
      "id": "f936503f-9291-42fa-ade8-e125faf89d6b",
      "object": "address",
      "live_mode": true,
      "line1": "123 Main St",
      "line2": "Suite 400",
      "locality": "San Francisco",
      "region": "CA",
      "postal_code": "94105",
      "country": "US",
      "created_at": "2019-11-09T00:11:07Z",
      "updated_at": "2019-11-09T00:11:07Z"
    },
    "account_details": [],
    "routing_details": [],
    "created_at": "2019-11-09T00:11:07Z",
    "updated_at": "2019-11-09T00:11:07Z"
  },
  "receiving_account_id": "5acec2ef-987b-4260-aa97-b719eeb0a8d5",
  "receiving_account_type": "external_account",
  "accounting_category_id": null,
  "currency": "USD",
  "effective_date": "2019-11-19",
  "priority": "normal",
  "description": null,
  "statement_descriptor": null,
  "remittance_information": null,
  "metadata": {},
  "status": "approved",
  "counterparty_id": "37ba4454-dd33-4aa0-8906-0e2e4103e45c",
  "transaction_ids": [],
  "charge_bearer": null,
  "foreign_exchange_indicator": null,
  "foreign_exchange_contract": null,
  "created_at": "2019-11-09T00:11:07Z",
  "updated_at": "2019-11-09T00:11:07Z"
}

The response contains the Payment Order ID (c5f4009c-bdd6-4cc1-84b2-17974ac9e77a) and its details.

Optional: Attach documents to the check

You can attach supporting documents to a check by including them in the Payment Order request. Modern Treasury supports two document types:

  • check_attachment: A document to include with the check (e.g., an invoice or remittance advice).
  • check_logo: An image to print (in grayscale) in the upper-left corner of your check. The image must meet the following requirements:
    • PNG or JPG format
    • RGB or CMYK color space
    • Square aspect ratio (equal width and height)
    • Minimum 100px × 100px
    • Transparent background

You can upload documents using either multipart form upload or base64 encoded file data.

Multipart form upload

Send a multipart/form-data request instead of application/json. Each document requires a file (the binary) and a document_type:

curl --request POST \
  -u ORGANIZATION_ID:API_KEY \
  --url https://app.moderntreasury.com/api/payment_orders \
  -H 'Content-Type: multipart/form-data' \
  -F type=check \
  -F amount=10000 \
  -F direction=credit \
  -F currency=USD \
  -F originating_account_id=0f8e3719-3dfd-4613-9bbf-c0333781b59f \
  -F receiving_account_id=5acec2ef-987b-4260-aa97-b719eeb0a8d5 \
  -F documents[][document_type]=check_attachment \
  -F documents[][file]=@/path/to/invoice.pdf \
  -F documents[][document_type]=check_logo \
  -F documents[][file]=@/path/to/logo.png

Base64 encoded file data

Alternatively, include documents inline as base64-encoded data in a standard application/json request. Each document requires file_data (the base64-encoded content), filename, and document_type:

curl --request POST \
  -u ORGANIZATION_ID:API_KEY \
  --url https://app.moderntreasury.com/api/payment_orders \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "check",
    "amount": 10000,
    "direction": "credit",
    "currency": "USD",
    "originating_account_id": "0f8e3719-3dfd-4613-9bbf-c0333781b59f",
    "receiving_account_id": "5acec2ef-987b-4260-aa97-b719eeb0a8d5",
    "documents": [
      {
        "document_type": "check_attachment",
        "file_data": "<base64 encoded bytes>",
        "filename": "invoice.pdf"
      },
      {
        "document_type": "check_logo",
        "file_data": "<base64 encoded bytes>",
        "filename": "logo.png"
      }
    ]
  }'

Optional: Handle post-creation events

Modern Treasury sends events as your Payment Order progresses. Use the Dashboard, Webhooks, or a third-party integration to receive these events — for example, to notify the counterparty, track delivery status, or confirm the check has been deposited.