Request a W-9
Collect a recipient's tax info ahead of 1099 issuance.
Goal
Email a US recipient a hosted W-9 form, capture their tax ID, and verify it. Once on file, the recipient is eligible for year-end 1099 issuance based on their cumulative payouts.
Prerequisites
- An existing recipient with a valid
email. - API key with Treasury + tax-documents enabled.
Implementation
1. Send the request
await client.requestW9({ recipient_id: "rcp_123…" });Endpoint: POST /treasury/recipients/{id}/request-w9. The recipient receives
an email with a hosted form. On submit, their tax ID is tokenized at intake
— your servers never see the raw value.
2. Check status
const { data: taxInfo } = await client.getRecipientTaxInfo("rcp_123…");
// taxInfo.tax_id_type: "ssn" | "ein" | "itin" | "none"
// taxInfo.w9_status: "not_requested" | "requested" | "received" | "verified" | "expired"
// taxInfo.w9_received_at, taxInfo.w9_expires_atStatuses progress: not_requested → requested → received → verified. The
verified state means our TIN-matching service confirmed the ID against
IRS records (where enabled for your account).
3. Backfill from your own form (alternative)
If you've collected the W-9 outside the hosted flow — e.g. via DocuSign or your own onboarding UI — you can post the tax-info fields directly:
await client.updateRecipientTaxInfo("rcp_123…", {
tax_id_type: "ssn",
tax_id: "123-45-6789", // tokenized at intake; never stored raw
w9_status: "received",
w9_received_at: new Date().toISOString(),
});Endpoint: POST /treasury/recipients/{id}/tax-info.
4. Pull the year-end report
const { data: report } = await client.getRecipientTaxReport();
// One entry per recipient with cumulative payout totals + W-9 readiness.Endpoint: GET /treasury/recipients/tax-report. Use this to drive your
1099 issuance — every recipient over the IRS threshold whose w9_status
isn't received or verified is a hole you need to chase before year-end.
Tradeoffs
- You don't see the tax ID. The full SSN/EIN is intentionally unreadable from your application after intake. If you need to surface it to the recipient (for them to confirm their own info), build a flow that re-prompts them rather than echoing it back.
requesteddoes not block payouts. A recipient withw9_status: "requested"can still receive payouts. If your policy is "no W-9, no pay," gate that yourself before callingcreatePayout.- Persons vs. businesses.
tax_id_typemust matchrecipient.type:ssn/itinforperson,einforbusiness. Wrong combinations are rejected at submission, not at recipient creation.