Create Recurring Transaction

Schedule a fixed-amount pay or collect to run automatically on a defined interval.

Creating a recurring transaction sets up a schedule once; PCE then generates the underlying transaction automatically on each due date. You define two things in one request: the schedule (transactionDetail) and the pay or collect it runs (action.transaction). Use it for rent, subscriptions, retainers, or any repeating money movement. For the full field list, jump to the Request reference.

The transaction a schedule runs is the same one you'd send as a one-off Pay or Collect; only the transactionDetail schedule wrapper is new.

Common use cases

  • Pay a landlord or vendor a fixed amount every month
  • Collect a subscription or membership fee on a set interval
  • Disburse a fixed retainer or allowance on a weekly or yearly cadence

Make your first recurring transaction

The fastest way to see it work: schedule a fixed monthly ACH payout to a saved vendor. Send a POST to /v1/transaction/recurring with the minimal fields below. The full set of options is in the Request reference.

POST /v1/transaction/recurring

{
  "name": "Monthly rent to landlord",
  "externalId": "recurring-rent-001",
  "transactionDetail": {
    "startDate": "08/01/2026",
    "occurrence": "12",
    "frequency": "MONTH",
    "interval": "1",
    "dayOfMonth": ["1"]
  },
  "action": [
    {
      "type": "TRANSACTION",
      "transaction": {
        "source": { "account": { "externalId": "passport-account-001" } },
        "destination": { "externalAccount": { "id": "4021726" } },
        "method": "ACH",
        "amount": "1200.00",
        "purpose": "Rent payment",
        "processingDetail": { "processingMode": "FORWARD", "authType": "WRITTEN" }
      }
    }
  ]
}

You'll get back 201 Created with a url header pointing at the new schedule (for example /v1/transaction/recurring/id/8176). The schedule starts in ACTIVE status. Store the returned id and your externalId to track it and for follow-up actions (update, pause, cancel).

📘

Use externalId for safe retries

For Treasury, PCE treats the externalId in the request body as the idempotency key; there's no separate header. Send a unique externalId per schedule, and retrying with the same value creates it only once. Once set, externalId can't be changed.


Scenarios

Every schedule uses the same request shape. What changes per scenario is the frequency (and the day/month fields it requires) and whether the action.transaction is a pay or a collect. Each generated transaction then follows the Transaction lifecycle.

Before you begin (all scenarios)

  • The source Passport Account is active and, for a pay, funded when each occurrence runs.
  • The destination (pay) or source (collect) resolves: a saved External Account, Contact, or mailing address.
  • For a collect, you hold authorization to debit the payer, and it's linked where your program requires it.

Scenario 1: Pay a fixed amount every month

(frequency: MONTH, requires dayOfMonth)

Use this for rent, a retainer, or any monthly payout of the same amount. Set dayOfMonth to the day it should run.

You'll also need: the payee's saved External Account or Contact.

Request

POST /v1/transaction/recurring

{
  "name": "Recurring payment of fixed amount to subcontractor",
  "externalId": "recurring-month-001",
  "transactionDetail": {
    "occurrence": "10",
    "frequency": "MONTH",
    "interval": "1",
    "dayOfMonth": ["1"]
  },
  "action": [
    {
      "type": "TRANSACTION",
      "transaction": {
        "source": { "account": { "id": "4056457" } },
        "destination": { "externalAccount": { "id": "4021726" } },
        "method": "ACH",
        "amount": "100.00",
        "purpose": "Rent payment",
        "processingDetail": {
          "processingMode": "FORWARD",
          "companyName": "AMEX",
          "companyDescription": "Rent",
          "authType": "WRITTEN"
        }
      }
    }
  ],
  "metaData": { "Landlord": "Cathy Drew" },
  "tags": ["Deposit"]
}

Response

201 Created, with a url header of the form /v1/transaction/recurring/id/{id}. Retrieve the schedule to read the stored resource (status: ACTIVE, nextTransactionDate, and the transactionDetail you set).

Scenario 2: Run on specific days every week

(frequency: WEEK, requires dayOfWeek)

Use this for a weekly cadence, for example a payout every Saturday and Sunday. Set dayOfWeek to one or more days.

You'll also need: the same source/destination as scenario 1.

Request

POST /v1/transaction/recurring

{
  "name": "Weekly payout to subcontractor",
  "externalId": "recurring-week-001",
  "transactionDetail": {
    "endDate": "06/30/2027",
    "occurrence": "15",
    "frequency": "WEEK",
    "interval": "1",
    "dayOfWeek": ["SATURDAY", "SUNDAY"]
  },
  "action": [
    {
      "type": "TRANSACTION",
      "transaction": {
        "source": { "account": { "id": "4056457" } },
        "destination": { "externalAccount": { "id": "4021726" } },
        "method": "ACH",
        "amount": "100.00",
        "purpose": "Weekly payout",
        "processingDetail": { "processingMode": "FORWARD", "authType": "WRITTEN" }
      }
    }
  ]
}

Response

201 Created, with a url header pointing at the new schedule.

Scenario 3: Collect a fixed fee on a schedule

(pull from a payer, with authorization)

Use this to debit a payer you're authorized to collect from, for example a subscription or membership fee. The action.transaction is a collect: the source is the payer's External Account or Contact and the destination is your Passport Account.

You'll also need: authorization to debit the payer. Collect via WIRE is supported only for Business Customers whose external account holderType is CORPORATE.

Request

POST /v1/transaction/recurring

{
  "name": "Monthly subscription fee",
  "externalId": "recurring-collect-001",
  "transactionDetail": {
    "startDate": "08/01/2026",
    "occurrence": "12",
    "frequency": "MONTH",
    "interval": "1",
    "dayOfMonth": ["1"]
  },
  "action": [
    {
      "type": "TRANSACTION",
      "transaction": {
        "source": {
          "contact": {
            "id": "4019600",
            "externalAccount": { "id": "4021726" }
          }
        },
        "destination": { "account": { "id": "4056457" } },
        "method": "ACH",
        "amount": "49.00",
        "purpose": "Subscription fee",
        "processingDetail": { "processingMode": "FORWARD", "authType": "ONLINE" }
      }
    }
  ]
}

Response

201 Created, with a url header pointing at the new schedule.

Scenario 4: Run once a year on a specific date

(frequency: YEAR, requires dayOfMonth + monthOfYear)

Use this for an annual payment, such as a yearly renewal or fee. Set both monthOfYear and dayOfMonth.

Request

POST /v1/transaction/recurring

{
  "name": "Annual renewal fee",
  "externalId": "recurring-year-001",
  "transactionDetail": {
    "endDate": "12/31/2030",
    "occurrence": "5",
    "frequency": "YEAR",
    "interval": "1",
    "monthOfYear": ["FEBRUARY"],
    "dayOfMonth": ["29"]
  },
  "action": [
    {
      "type": "TRANSACTION",
      "transaction": {
        "source": { "account": { "id": "4056457" } },
        "destination": { "externalAccount": { "id": "4021726" } },
        "method": "ACH",
        "amount": "100.00",
        "purpose": "Renewal fee",
        "processingDetail": { "processingMode": "FORWARD", "authType": "WRITTEN" }
      }
    }
  ]
}

Response

201 Created, with a url header pointing at the new schedule.


Track the schedule and its transactions

Retrieve the schedule with a GET to /v1/transaction/recurring/id/{id} (or /externalId/{externalId}) to read its current status, statusReason, and nextTransactionDate. To see the transactions a schedule has generated, use Find & track recurring transactions. Each generated transaction is a normal Treasury transaction; track it and subscribe to its webhooks via the Transaction lifecycle.


Request reference

The complete set of fields for the create-recurring-transaction request.

Top-level parameters

ParameterRequiredDescription
nameName of the recurring instruction.
transactionDetailThe schedule. See Schedule (transactionDetail).
actionArray with one element describing what runs. action[0].type is optional (TRANSACTION); action[0].transaction is required. See Action (action.transaction).
externalIdRecommendedYour own reference ID, also the idempotency key. Unique across recurring transactions; can't be updated once set. Maximum 45 characters.
linkedDocumentOptionalArray of authorization documents that authorize the fund movement. See Linked documents.
commentOptionalFree-text comment. Maximum 512 characters.
metaDataOptionalKey/value pairs for your own additional information.
tagsOptionalLabels assigned to the schedule.

Schedule (transactionDetail)

ParameterRequiredDescription
frequencyHow the interval is counted: CALENDAR_DAY, BUSINESS_DAY, WEEK, MONTH, or YEAR. Can't be changed after creation.
intervalGap between two occurrences, in units of frequency.
startDateOptionalWhen the schedule begins. Current or future date.
endDateOptionalWhen the schedule ends. Must be after startDate.
occurrenceOptionalTotal number of occurrences to run.
dayOfWeekConditionalDay(s) of week. Required when frequency is WEEK. Not allowed for CALENDAR_DAY or BUSINESS_DAY.
dayOfMonthConditionalDay(s) of month. Required when frequency is MONTH or YEAR. Not allowed for CALENDAR_DAY, BUSINESS_DAY, or WEEK.
monthOfYearConditionalMonth(s) of year. Required when frequency is YEAR. Not allowed for CALENDAR_DAY, BUSINESS_DAY, WEEK, or MONTH.

Action (action.transaction)

action[0].transaction reuses the transaction model. Both source and destination are required and depend on whether you're paying or collecting and on the method.

ParameterRequiredDescription
methodRail: ACH, WIRE, CHECK, BOOK, INTERNATIONAL_WIRE, or VIRTUAL_CARD.
amountFixed amount per occurrence, in USD. Must be greater than zero.
purposePurpose of the transaction.
sourceWhere funds come from. See the source/destination table below.
destinationWhere funds go. See the source/destination table below.
processingDetailConditionalRail-specific processing options; see Processing detail.

Source and destination by intent and method

Intentsourcedestination
Pay (ACH)account.idexternalAccount.id
Pay (CHECK)account.idaddress.id
Pay (BOOK)account.idaccount.id
Pay (INTERNATIONAL_WIRE)account.idinternationalExternalAccount.id (+ currency)
Collect (ACH)externalAccount.id, or contact.id + contact.externalAccount.idaccount.id
Collect (WIRE)externalAccount.id (CORPORATE holderType only)account.id

Reference entities by id (assigned by Passport) or externalId (your reference).

Processing detail

processingDetail fields depend on the method, and certain fields may be required by your program's configuration. These mirror the one-off transaction fields.

MethodFields
ACH / WIREprocessingMode (FORWARD default, SAME_DAY), companyName, companyDescription, authType (WRITTEN, PHONE, ONLINE), addenda, memo, location.id, payor
CHECKdeliveryMode (STANDARD default, TWO_DAY, OVERNIGHT), remittanceInfo, memo, location.id
BOOKpurpose (max 255), memo (max 255)
INTERNATIONAL_WIREmemo (max 140), location.id, wireReference
VIRTUAL_CARDvirtualCard (nickname, cardProgram.id, entity.id, location.id)

For the full processing-detail semantics per method, see the matching one-off method page under Pay or Collect.

Linked documents

linkedDocument is an array. Each entry links an authorization document that authorizes the fund movement.

ParameterRequiredDescription
linkedDocument[].purposePurpose of the document. Value: AUTHORIZATION.
linkedDocument[].document.nameFile name.
linkedDocument[].document.typeDocument type. Value: CONTRACT.
linkedDocument[].document.base64encodedContentBase64-encoded file. Allowed: pdf, jpg, bmp, txt, tiff, rtf, doc, docx, xls, csv, wav, jpeg, png, xlsx, efx.

Validation

The prerequisites above are the validations, and PCE enforces them when you submit. If a check fails, the request returns an error and no schedule is created.

Submit-time checks:

  • Required fields are present and correctly formatted, including the conditional day/month fields for the chosen frequency.
  • externalId is unique across recurring transactions.
  • endDate is after startDate.
  • startDate is the current date or a future date.
  • The source and destination resolve for the chosen method and intent.

For the codes returned when a check fails, see Recurring Transaction Error Codes.


Statuses

A new schedule starts in ACTIVE. The schedule statuses (ACTIVE, PAUSED, CANCELLED, COMPLETED) and their reasons are on Recurring transactions. Each transaction the schedule generates follows the shared Transaction lifecycle.


Go live

The shared pre-production checklist (production credentials, webhook subscription and signature validation, idempotency, and sandbox testing) is in Getting Started. Specific to creating a recurring transaction, also confirm:

  • The chosen method is enabled for your program (INTERNATIONAL_WIRE and VIRTUAL_CARD may require enablement).
  • For collects, authorization is held and linked as linkedDocument where required.
  • The day/month fields match the frequency so occurrences fall on the dates you expect.

Best practices

General practices (unique externalId, subscribe to webhooks, test in sandbox) are in Getting Started. Specific to recurring transactions:

PracticeDescription
Set an endDate or occurrenceBound every schedule so it completes on its own instead of running indefinitely.
Confirm the schedule with a GETThe create response has no body; retrieve the schedule to verify nextTransactionDate and stored transactionDetail.
Fund the source before each runA schedule doesn't reserve funds; ensure the source Passport Account is funded ahead of each occurrence.
Track generated transactions by webhookEach occurrence emits its method's usual transaction webhooks; don't poll the schedule for per-transaction status.

Next steps

See also



Did this page help you?
.readme-logo { display: none !important; }