Easy Labs
TreasuryGuides

Invite a recipient

Have a recipient enter their own banking through a one-time link.

Goal

Create a recipient record without their banking, then email them a 72-hour self-serve link where they enter their bank details through Plaid Link. The recipient is fully payable when they finish — no account numbers ever pass through your servers.

Prerequisites

  • An API key with Treasury enabled.
  • The recipient's name and email.

Implementation

1. Create the recipient (banking optional)

const { data: recipient } = await client.createRecipient({
  name: "Grace Hopper",
  email: "grace@example.com",
  type: "person",
  payment_methods: [], // empty — they'll add it via the invite
});

2. Send the invite

await client.inviteRecipient({ recipient_id: recipient.id });

This emails the recipient a one-time link. The link is valid for 72 hours; sending another invite to the same recipient revokes the previous one. The underlying endpoint is POST /treasury/recipients/{id}/invite.

The hosted page at the invite URL handles everything. Under the hood it calls POST /treasury/recipients/plaid/link-token (using the invitation_token from the URL, not your API key) and on success calls POST /treasury/recipients/plaid/exchange to attach the verified bank account.

You don't ship code for this step — it's a hosted flow. If you want to embed it in your own UI later, the recipient-plaid endpoints are the same contract.

4. Detect completion

Poll the recipient until a payment method appears:

const { data } = await client.getRecipient(recipient.id);
const ready = (data.payment_methods ?? []).length > 0;

You can list all pending invitations with client.listRecipientInvitations() to surface a "waiting on Grace" UI.

5. (Optional) Capture tax info in the same flow

If the recipient is a US contractor and you'll cross the 1099 threshold, chain a W-9 request right after the bank link:

if (ready) {
  await client.requestW9({ recipient_id: recipient.id });
}

Tradeoffs

  • You don't see the bank details. Only account_number_last4, routing_number, and the institution name are returned. If a recipient disputes that you sent to the wrong account, the audit trail is the Plaid link event, not a visible account number.
  • Invitations expire. 72 hours, full stop. For long-tail onboarding (contractors who sign up months before getting paid), trigger the invite on first payout instead of at recipient creation.
  • Manual entry alternative. If your recipients can't or won't use Plaid, call client.addRecipientPaymentMethod(...) server-side with routing_number + account_number. The number is tokenized at intake but you've now seen it, which puts you in scope for the data handling requirements documented in Compliance.

On this page