API Docs
Guides

Pay with a payout link

Create a payout for an email address and let the recipient claim it on a Talentir-hosted page.

You know the recipient's email address and nothing else. Create a payout for that email, get it approved, and hand the recipient a claim link. On the Talentir-hosted page they sign in with a one-time code, choose a payout method, and claim the money. Talentir collects the payment details and runs verification, so your product never stores them.

1. Create the payout

curl -X POST "$BASE_URL/payouts" \
  -H "Authorization: Bearer $TALENTIR_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "customId": "campaign-42",
    "description": "Payment for September campaign",
    "amount": "100.00",
    "currency": "EUR",
    "recipient": { "type": "email", "email": "jane@example.com" },
    "tags": ["september"]
  }'

The response has status 201 and is the payout as GET /payouts/{id} returns it. Every field is present; a field with no value is null. The payout starts in status created.

Fields:

  • description (required) — shown to the recipient. 1 to 5000 characters. It can span several lines: a literal \n becomes a line break, and consecutive line breaks collapse into one.
  • amount (required) — a decimal string such as "100.00", minimum 0.10. Never a float.
  • currency (required) — USD, EUR, CHF, or GBP.
  • recipient (required) — { "type": "email", "email": "…" }. No Talentir account is needed yet. Add an optional phone (E.164) when your team sends claim links by SMS. A saved counterparty with an email can also receive a claim link.
  • customId — your own key, unique within your team. It works in place of the payout_… id wherever a payout is referenced, for example as {id} in a path. A second request with the same customId is refused. See Idempotency.
  • availableOn — a UTC calendar date (YYYY-MM-DD) before which the payout cannot be claimed. Omit for immediately claimable.
  • tags — free-form strings for categorizing payouts; filterable with ?tag= on GET /payouts. Up to 20 tags, each 1 to 100 characters.
  • locked — true makes the payout refuse PATCH and dashboard edits. Only delete is left.
  • andThen — runs the later steps in the same request: approve or approve_and_send_claim_link. Both need payouts:approve. The request either does every step or none. The claim link email goes out only after the approval is saved. If it cannot be sent, the payout stays approved with claimLinkSentAt: null; call send-claim-link again.

Send an Idempotency-Key header on every POST, so a retried request replays the response instead of creating a second payout.

Payouts to a TikTok, Instagram, or YouTube handle, or to a wallet address, cannot be created through v2. Those created through v1 read back with recipient.type of tiktok, instagram, youtube_channel, or wallet. To pay a wallet, save it as a counterparty's crypto payment method and pay directly.

For every parameter and the full response schema, see the Payouts reference.

2. Get it approved

A created payout waits for your team's approval, which reserves the amount against your balance. Approve it in the dashboard, on a hosted approval screen, or through the API. See Approve payouts.

With payouts:approve, andThen: "approve_and_send_claim_link" on create does steps 1 to 3 in one request.

An approved payout waits for you to send the link. Pick one:

Let Talentir email it.

curl -X POST "$BASE_URL/payouts/campaign-42/send-claim-link" \
  -H "Authorization: Bearer $TALENTIR_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

This emails the recipient and sets claimLinkSentAt. Calling it again resends and restarts the reminder schedule. It needs payouts:write and a recipient with an email.

Send it yourself. Mint the URL and put it in your own email, or redirect the recipient to it from your product:

curl -X POST "$BASE_URL/sessions" \
  -H "Authorization: Bearer $TALENTIR_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "payout_claim",
    "payoutId": "campaign-42",
    "redirectUrl": "https://yourapp.com/done"
  }'

The response carries a url. Treat it as opaque: redirect the recipient to it as is, and do not parse or build it. The URL confers no access on its own; the screen still authenticates the visitor, so the link is safe to email. redirectUrl is where the recipient returns after claiming or leaving the screen; it must be an absolute https URL (http only for localhost). Add branding: "team" to host the page on your white-label subdomain with your logo. See Pay on behalf of your customers for every session field.

4. What the recipient sees

The recipient signs in or signs up with their own email, chooses a payout method (bank account, PayPal, Venmo, or a crypto wallet), and claims. The claim moves the payout to requested, and Talentir requests the transfer. Talentir keeps the recipient's details as a counterparty with recipientManaged: true, so a later payout to the same email can be paid directly.

By default Talentir issues a self-billing invoice in the recipient's name for every payout and returns it as recipientInvoiceUrl. With the invoice_upload feature enabled for your organization, recipients can upload their own invoice while claiming instead. Talentir reads the document and checks it against the payout: the amount and currency, the party it is addressed to, the issuer, and the VAT treatment. recipientInvoiceSource (self_billing or recipient_upload) tells you which document you got.

5. Track the payout

Subscribe to webhooks for payout.approved, payout.requested, and payout.completed, or poll GET /payouts/{id}. A provider rejection after the claim sends the recipient to a retry flow where they fix their details; see Payout lifecycle.

Manage payouts

These apply to every payout, however it is sent.

Create many at once. POST /payouts/batch takes { "payouts": [ ... ] } with up to 100 items, each a POST /payouts body. It creates all of them or none, and answers with a list in request order. See Batches.

Update. PATCH /payouts/{id} changes a payout while its status is created. An omitted field is unchanged; recipient is replaced as a whole. A payout in another status is 409 PAYOUT_NOT_EDITABLE, a locked one 409 PAYOUT_LOCKED.

Delete. A payout can be deleted as long as no transfer is in flight: while its status is created, approved, failed, or expired. Deleting emits payout.deleted.

curl -X DELETE "$BASE_URL/payouts/campaign-42" \
  -H "Authorization: Bearer $TALENTIR_API_KEY"

The response is { "object": "payout", "id": "payout_…", "deleted": true }. A requested or completed payout cannot be deleted; the request fails with 409 PAYOUT_NOT_DELETABLE. After the delete, the payout is gone from the API: every endpoint answers 404 PAYOUT_NOT_FOUND for it, and lists do not include it. Its customId stays taken: a create with it fails with 409 CUSTOM_ID_TAKEN. To redo the payout, use a new customId.

List. GET /payouts returns a list envelope, newest first. Filter with status (repeatable), recipientCounterpartyId, tag (repeatable), createdFrom (inclusive), and createdBefore (exclusive). Page with limit (1 to 100, default 20) and the nextCursor of the previous page as cursor.

{ "object": "list", "data": [ … ], "hasMore": true, "nextCursor": "eyJ…" }

Sandbox test scenarios

In the sandbox, every payout method has a passing and a failing scenario. Success is the default: any regular recipient details settle the payout instantly and synchronously, including the webhook events a real payout would emit. To exercise the failure path, use these magic values on the claim screen, or on the counterparty for a direct payout:

MethodFailure trigger
SEPA (bank_iban), SWIFT (bank_swift), ACH (bank_ach), Fedwire (bank_wire), UK Faster Payments (bank_uk)Account holder name containing SANDBOX FAIL (for a counterparty, its identity.lastName or identity.name)
PayPal (paypal), Venmo (venmo)Recipient email containing sandbox-fail (e.g. sandbox-fail@example.com), or a Venmo phone number ending in 0000
Crypto (crypto)Destination wallet address 0x000000000000000000000000000000000000dEaD (for a counterparty, its paymentMethod.walletAddress)

A triggered failure behaves like a real provider rejection: the transfer is dispatched, then declined. A claimed payout goes to the recipient's retry flow. A direct payout to a counterparty becomes failed with a failureReason, and payout.failed fires instead of payout.completed.