# Payments API PRD: asynchronous merchant payout
Synthetic filled-in example. Adapt to the actual provider contract, approved funds flow and operating permissions. This is a product specification, not an implemented API or universal HTTP contract.

Companion guide: https://rzifi.com/blog/payments-prd-template-nine-sections/

## Problem and intended outcome
An authenticated merchant submits one payout instruction and needs a reliable status without creating duplicate movement after a timeout. Success is explainable outcomes and no duplicate execution for the same instruction. Measure those outcomes in a pilot; no pilot results are asserted here.

## Users and authority
Merchant operator can create an instruction within approved limits. Payment operations can investigate but cannot create a compensating transfer merely to close a ticket. Treasury owns funding; an authorized approver owns releases and adjustments. Scope each request to the authenticated tenant and merchant. Reject cross-tenant identifiers without disclosure.

## Scope and non-goals
One corridor and currency, one contracted provider and explicitly funded merchant balances. Include submission, inquiry, callbacks and reconciliation. Exclude lending, automatic FX conversion, autonomous refund execution and an assurance of beneficiary receipt from a provider acknowledgement.

## Illustrative API and idempotency contract
POST /v1/payouts requires a merchant-scoped Idempotency-Key, integer amount_minor, currency, validated beneficiary reference and merchant_reference. For this example, accepted instructions return HTTP 202 with an immutable payment_id and status=submitted. A repeated key with the same normalized request returns the original instruction and its current state, without a second execution. A changed payload under the same key returns HTTP 409. Specify canonicalization, retention duration and expiry behavior before implementation; never rely on this sample as a provider guarantee.

GET /v1/payouts/{payment_id} returns the authoritative local record with provider reference, evidence timestamp and state provenance. A timeout on POST is an unknown outcome, not a failure. Reconcile or query the original attempt with the same identity; do not generate a fresh key to bypass ambiguity.

## State and evidence model
Created → validated → submitted → pending → succeeded or failed. Unknown is an investigation condition for missing or conflicting evidence, not a terminal financial outcome. A succeeded state requires the contracted authoritative evidence; distinguish provider acceptance, beneficiary credit and bank settlement in separate fields. Reversal is a separate linked event with its own evidence and accounting effects. Preserve event history rather than overwriting inconvenient states.

## Webhooks and recovery
Authenticate callbacks with the agreed provider scheme. Persist the raw verified event and deduplicate by provider event identity. Acknowledge only after durable acceptance. Handle out-of-order delivery using provider version/sequence or authoritative inquiry, not the arrival timestamp alone. Retry with backoff, cap attempts and route unresolved delivery to an owned queue. Periodic reconciliation catches missing callbacks. No callback absence or browser redirect alone establishes payment failure.

## Funds, refunds and reconciliation
Check funded availability and approved limits using the defined ledger contract. Record fees, settlement currency and provider/bank references separately. Refund or reversal requests require authority, eligible original state and a separate idempotency scope. A lost refund response triggers inquiry, not a second refund. Do not promise that routing rollback can undo money already moved.

## Compatibility and release
Document /v1 field semantics and error codes. Additive optional fields must not break tolerant clients; changed enum behavior needs a migration policy. Test old client fixtures and provider contract versions. Shadow reconciliation before enabling money movement; use a limited pilot with named go/no-go approvers and explicit stop conditions.

## Acceptance evidence
- The same tenant/key/payload sent concurrently produces one instruction and at most one authorized execution.
- Changed payload under that key returns 409 with no new execution.
- Lost submission response followed by inquiry retains the original payment identity.
- Duplicate or reordered callbacks do not regress a terminal state or create a second posting.
- Missing provider evidence remains unresolved and assigned, never presented as paid.
- Cross-tenant requests disclose no transaction details.
- Refund timeout preserves its reference and blocks blind retry.
- Ledger, provider and bank differences are classified with owners before pilot exit.

## Open decisions and ownership
Product: success criteria and supported statuses. Engineering: atomic idempotency storage and recovery. Provider owner: inquiry and callback contract. Finance: fee and settlement accounting. Security/legal: applicable permissions, data handling and authorization. Operations: response targets, escalation and hypercare exit. Resolve each with dated evidence before approving production use.
