Skip to main content
Direct is in early access and subject to change. To request Direct access, contact hi@natural.com.
Use Direct to pay a person or business that isn’t on Natural, straight to their bank.
  1. Save the payee once as an external party.
  2. Add their bank account.
  3. Send over ACH, realtime, or wire.
To pay by email, phone, or handle instead, see Send a payment.

Choose a rail

Create the external party

Create the payee with POST /external-parties. kind (individual or business) and name are required; an individual’s name needs a first and last name. Include a complete address if you will send wires.
Natural screens every external party and reports the result in screeningStatus: clear, under_review, or rejected. A rejected party cannot have bank accounts stored or be paid.

Store the bank account

Store the payee’s US bank account with POST /external-party-accounts. The response never returns the full numbers, only last4 and a mask.
  • supportedRails lists the rails the account is expected to accept (ach, realtime, wire). It is advisory; the authoritative check runs when you create the payment.
  • validationState starts validated or pending. A pending account resolves asynchronously and fires external_party_account.validated when it validates. ACH credits work while it is pending. A failed account cannot be paid; store a new one.
Store the account once and reuse its epa_* for every later payment to that payee. List a payee’s saved accounts with GET /external-party-accounts?externalPartyId=epty_....

Send the payment

Every Direct create takes an Idempotency-Key. Retry a timed-out create with the same key and body; a reused key with a different body returns 409 idempotency_key_reused. The payment draws from your default wallet; pass walletId (wal_*) to spend from a specific wallet, and an agent with access to more than one wallet must pass it.
POST /ach with direction: "credit". companyEntryDescription (up to 10 characters, uppercased) appears on the payee’s bank statement. Optional addenda (up to 80 characters) carries remittance data to the receiving bank.
The response carries the payment ID and its initial status. An ACH payment looks like this: A payment that breaches a limit starts at AWAITING_APPROVAL and moves on once it is approved. Common create errors: Each rail’s full list is on its errors page: ACH, realtime, wire.

Track the payment

Read one payment with its rail’s get endpoint, for example GET /ach/{achId}, or list them with filters such as status and externalPartyId. Direct payments also appear in GET /transactions alongside the rest of your money movement.
Every rail starts at CREATED and moves to PROCESSING once submitted. The terminal states differ by rail: The fee is assessed at submission, so fee is null until the payment reaches PROCESSING. Rather than polling, subscribe to the rail’s webhooks: ach.*, realtime.*, and wire.*. Approval holds emit approval.*. Payloads are in the event catalog.

Cancel a payment

ACH, realtime, and wire payments can be canceled only before submission, while they are CREATED or AWAITING_APPROVAL. Cancel takes a reason and an Idempotency-Key; once submission starts it returns 400 <rail>.not_cancellable.

Test in the sandbox

Sandbox Direct payments don’t reach a real bank. Drive them to a terminal state with simulations:

Initiate payment for a customer

An agent connected to a customer can pay that customer’s vendors and contractors from the customer’s wallet. The flow is the same as above with one field added, customerPartyId, on every call: in data.attributes for creates and cancels, and as a query parameter for reads. For the connection model, read the Customers overview.

Ask for Direct permissions

Direct needs its own grants on the customer connection. Request them when you invite the customer. direct.create implies direct.read, and external_parties.create implies external_parties.read. direct.create can be granted only to an agent, so Direct calls for a customer authenticate with the agent’s key and name the run with X-Instance-ID.
A customer connected before you asked for Direct must approve a new invitation that includes these permissions. Each rail must also be enabled on the customer’s account, not just yours. If it isn’t, create returns 403 ach.not_enabled (or realtime.not_enabled, wire.not_enabled).

Create the payee under the customer

Your customers’ party IDs (pty_*) are on GET /customers; see Manage access. External parties and their accounts belong to one party. Create them with customerPartyId so they belong to the customer. A payee you created for your own party can’t be paid from a customer’s wallet.
To reuse payees the customer already has, list them with GET /external-parties?customerPartyId=pty_... and GET /external-party-accounts?customerPartyId=pty_...&externalPartyId=epty_....

Pay from the customer’s wallet

Add customerPartyId to the rail’s create. The payment draws from the customer’s default wallet, or the customer wallet you name in walletId, and counts against the limits on your connection. ACH is shown; POST /realtime and POST /wire take the same field.
The response’s customerParty relationship is the customer and wallet is the customer’s wallet, confirming the funds came from them. Abridged:
  • The customer is the sender. The payee’s bank statement shows the customer’s legal name as the ACH company name (submittedDescriptor.companyName), not yours. The customer needs a legal name, or a first and last name, or create returns 400 party.descriptor_name_unavailable.
  • Approvals. A payment over your connection’s limits starts at AWAITING_APPROVAL and waits for the customer to approve it.
  • Access is rechecked. Natural checks the connection again before submitting a payment. If the customer revoked it or removed direct.create in the meantime, the payment is not sent.

Track and cancel for the customer

Pass customerPartyId as a query parameter on reads and in data.attributes on cancel. Without it, reads look in your own party and return 404 for the customer’s payments.
Lifecycles, cancel windows, and errors are the same as for your own payments; see Track the payment.

Webhooks

ach.*, realtime.*, and wire.* events for the customer’s payments go to your webhooks that include "connected" in sources, while your connection holds direct.read (implied by direct.create). Payloads are in the event catalog.