YesCash Core API

Version 1.0.0

Ctomer Core API for profile, KYC, beneficiaries, quotes, transfers, funding and transfer stat.

Overview

# YesCash Core API

This OpenAPI file is the partner-facing contract for ctomer Core API operations.

It covers:

- ctomer profile;
- KYC sessions;
- beneficiaries;
- quotes and disclosures;
- quote acceptance;
- transfer submission;
- device-bound transfer confirmation;
- funding webview;
- transfer detail and list;
- cancellation;
- ctomer-visible stat handling;
- Core API error responses.

All Core API calls require a ctomer access token issued by the Authentication API.

Base URL:

```text
https://api.yes.cash
```

Servers

Endpoints

Endpoint Reference

POST /v1/core/profile

Submit ctomer profile (identity-attribute capture).

Ctomer profile submission per `§B.2.2`. Captures the minimum identity-attribute set for sanctions screening and KYC document matching; triggers identity resolution per the API specification silent merge across the three outcomes); the response shape is uniform across all three outcomes per `§B.2.2.2` silent-merge defence. Sanctions screening per the API specification post-submit; outcomes surface via `GET /v1/core/profile` (`stat`, `kycStat`) and the `ctomer.stat_changed` webhook stream. **Self-referential URL convention.** Per `§B.1.4` Part B URL convention, this is `POST /v1/core/profile`, NOT `/v1/core/profile/me` or `/v1/core/ctomers/{id}/profile`. Per FM.3.11, POST-as-update — the same endpoint handles both create (`PENDING` ctomer's first submission) and update. **Idempotency.** Within `PENDING` per `§B.2.2.5`; same idempotency key returns the original response. Post-`PENDING` profile-update semantics: forward dependency on the post-VALID profile-update workflow (out of v1 scope per `§B.4.4`).

Parameters

NameInRequiredTypeDescription
XCorrelationIdHeader
XIdempotencyKeyHeader

Request body

application/json: ProfileSubmitRequest

Responses

StatusDescriptionSchema
200Profile submission accepted. Response shape is uniform across the three identity-resolution outcomes per `§B.2.2.2`. The ctomer remains in `PENDING` post-submission; transition to `VALID` is gated on KYC completion per matrix v4 `§4.1`.application/json: ProfileSubmitResponse
400BadRequest
401Unauthorized
403Forbidden
409Conflict
415UnsupportedMediaType
429TooManyRequests
500InternalServerError
503ServiceUnavailable

GET /v1/core/profile

Read authenticated ctomer's profile, stat, KYC state, identifiers.

Profile-read per `§B.2.3`. Substantive ctomer-state observation surface — consumed at ctomer-app login-success per the `§A.7` profile-fetch-then-gate pattern, at navigation to profile / stat screens, and at state refresh in response to the `ctomer.stat_changed` webhook. Carries: identity attributes (echoed and post-processed); current stat per matrix v4 `§2`; KYC lifecycle state; currently-active identifier set per `§A.8.2`; partner-scoped `subscriptionId`.

Parameters

NameInRequiredTypeDescription
XCorrelationIdHeader

Responses

StatusDescriptionSchema
200Profile read.application/json: ProfileReadResponse
401Unauthorized
403Forbidden
429TooManyRequests
500InternalServerError
503ServiceUnavailable

POST /v1/core/kyc-sessions

Initiate principal-served KYC capture session.

KYC session creation per `§B.4.2`. **Empty request body** — session-purpose is determined server-side from the ctomer's KYC lifecycle state per the API specification `kycStat = NOT_STARTED`; resume for `IN_PROGRESS`; `RESUBMISSION` for `RESTRICTED` + `REMEDIATION_REQUIRED`). The empty-body posture preserves the structural defence that **the principal owns the KYC decision** per platform rules. Returns a session-bound webview URL on the principal-controlled `kyc.{YesCash}.yescash.example` host. Partner-app opens the URL in an in-app webview; capture happens entirely in the principal's environment; partner-app is the display host only. See `§B.5` for the webview wire-level behaviour and closure-signal handling. **Server-side idempotency** per `§B.4.2.5` — an existing in-progress session within TTL is returned for resumability; the `X-Idempotency-Key` is still required per FM.5. **Path convention.** Hyphenated `/kyc-sessions` per `§B.0.3` + `§B.4.2.1`; App B DevGuide's `/kyc/sessions` form is editorial drift and is surfaced as the API specification.3` candidate.

Parameters

NameInRequiredTypeDescription
XCorrelationIdHeader
XIdempotencyKeyHeader

Responses

StatusDescriptionSchema
200KYC session created or resumed.application/json: KycSessionCreateResponse
400BadRequest
401Unauthorized
403Forbidden
429TooManyRequests
500InternalServerError
503ServiceUnavailable

GET /v1/core/kyc-sessions/{kycSessionId}

Read KYC session lifecycle state.

KYC session-state read per `§B.4.3`. **Session-lifecycle only** — no KYC outcome details, no verification-pipeline state, no artefact-level signal. KYC outcomes surface via `GET /v1/core/profile` (`kycStat` field) and the `ctomer.stat_changed` webhook stream (Partner-Only spec). The deliberate split keeps `§B.4.3` as session-lifecycle-only surface; outcome-surfacing duplication is avoided per `§B.4.3`.

Parameters

NameInRequiredTypeDescription
KycSessionIdPathParam
XCorrelationIdHeader

Responses

StatusDescriptionSchema
200KYC session lifecycle state.application/json: KycSessionReadResponse
401Unauthorized
403Forbidden
404NotFound
429TooManyRequests
500InternalServerError
503ServiceUnavailable

POST /v1/core/quotes

Create a partner-issued signed quote (re-presented to principal).

Quote creation per App B flow B.2 + `§B.18.6` sandbox reachability. The partner-app re-presents the ctomer's pricing intent to the principal; the principal applies the the API specification.5 three-measure pricing envelope per `§D5` and returns a signed quote per `§D3`. **Note on inventory.** `§B.0.3` section-structure table omits this endpoint; App B canonical wire traces and the `§B.18.6` sandbox reachability table treat it as load-bearing. This YAML follows App B / `§B.18.6` per Step 27 Q1a. The `§B.0.3` inventory gap is surfaced as an the API specification.3` editorial-cleanup candidate (additive correction; no substantive contract change). **Quote validity.** 60-second TTL per `§B.6` general case; 30-minute CFPB ceiling for -YesCash quotes per the API specification.5 `§D4`.

Parameters

NameInRequiredTypeDescription
XCorrelationIdHeader
XIdempotencyKeyHeader

Request body

application/json: QuoteCreateRequest

Responses

StatusDescriptionSchema
200Signed quote created.application/json: QuoteResponse
400BadRequest
401Unauthorized
403Forbidden
409Conflict
415UnsupportedMediaType
422UnprocessableEntity
429TooManyRequests
500InternalServerError
502BadGateway
503ServiceUnavailable

GET /v1/core/quotes/{quoteId}

Fetch a signed quote by id.

Quote-detail read per `§B.6.2`. Observational; no state transitions. Ctomer-stat gating permits `VALID`, `MONITORED`, `RESTRICTED`; `PENDING` MAY fetch if the partner-app has surfaced a quote pre-promotion; `BLOCKED` / `CLOSED` reject. Quote mt resolve in the ctomer's `Subscription` scope per `§B.1.3` partner-scoping at the data layer.

Parameters

NameInRequiredTypeDescription
QuoteIdPathParam
XCorrelationIdHeader

Responses

StatusDescriptionSchema
200Quote returned.application/json: QuoteResponse
401Unauthorized
403Forbidden
404NotFound
429TooManyRequests
500InternalServerError
503ServiceUnavailable

GET /v1/core/quotes/{quoteId}/disclosure

Fetch regulator-aligned disclosure for a quote.

Regulator-aligned disclosure per `§B.7`. Returns a `disclosureToken` binding the served disclosure version to the `(quoteId, MasterCtomerId)` context; the token is single-e at acceptance per `§B.7.3`. The ctomer cannot accept a quote without first fetching this disclosure — the substantive ctomer-protection defence is that acceptance is committed against a regulator-aligned disclosure. **Language negotiation.** Per `§B.7.2.3`: `Accept-Language` → ctomer profile preference → YesCash default. **Caching.** `Cache-Control: no-store` per RFC 7234 — disclosure token is single-e and time-bound; caching is operationally wrong.

Parameters

NameInRequiredTypeDescription
QuoteIdPathParam
XCorrelationIdHeader
AcceptLanguageHeader

Responses

StatusDescriptionSchema
200Disclosure served.application/json: DisclosureResponse
401Unauthorized
403Forbidden
404NotFound
409Conflict
410Gone
429TooManyRequests
500InternalServerError
503ServiceUnavailable

POST /v1/core/quotes/{quoteId}/accept

Accept a quote (pricing commitment; creates transfer at registered).

Quote-acceptance per `§B.6.3`. The ctomer commits to the pricing terms; the principal creates the transfer shell in **`registered`** state per the API specification.1 `§D2` + matrix v4 `§4.12` `TRF_INITIATION_QUOTE_ACCEPTED`. The next state transition is driven by `/transfers/{id}/submit` (`§B.9`) — which attaches beneficiary + payout method + purpose and triggers the fast-check pipeline. **Ctomer-stat gating (G2 per `§B.16`).** `VALID` / `MONITORED` permit; `RESTRICTED` rejects with `ctomer.statBlocking`; `PENDING` rejects with `ctomer.statInsufficient`. The three-measure pricing envelope is re-checked at acceptance time; envelope-breach returns `quote.envelopeBreach` (422). **Idempotency.** Same key returns the original 201 with same `transferId`; the principal does NOT switch to 200 on retry per FM.5. **Three ctomer-commitment moments.** Per `§B.12.5`: (1) pricing commitment here at `/accept`; (2) recipient + destination commitment at `/submit`; (3) release-funds commitment at `/confirm` via device-bound assertion.

Parameters

NameInRequiredTypeDescription
QuoteIdPathParam
XCorrelationIdHeader
XIdempotencyKeyHeader

Request body

application/json: QuoteAcceptRequest

Responses

StatusDescriptionSchema
201Quote accepted; transfer shell created at `registered`.application/json: QuoteAcceptResponse
400BadRequest
401Unauthorized
403Forbidden
404NotFound
409Conflict
412PreconditionFailed
415UnsupportedMediaType
422UnprocessableEntity
429TooManyRequests
500InternalServerError
503ServiceUnavailable

GET /v1/core/beneficiaries

List the ctomer's beneficiaries.

Paginated beneficiary list per `§B.8.3`. Default state filter **excludes ARCHIVED**; partner-app may include ARCHIVED via the `states` query parameter for archived-list views. Cursor pagination per FM.3.10. Sort: `lastedAt` descending (most recently ed first); then `createdAt` descending for never-ed beneficiaries. Sort is fixed at v1.

Parameters

NameInRequiredTypeDescription
XCorrelationIdHeader
statesqueryNostringComma-separated list of `BeneficiaryState` values. Default: `VALID,MONITORED,BLOCKED,PENDING` (excludes ARCHIVED).
cursorqueryNostringOpaque pagination cursor per FM.3.10; omitted on first page.
limitqueryNointeger

Responses

StatusDescriptionSchema
200Beneficiary list.application/json: BeneficiaryListResponse
400BadRequest
401Unauthorized
403Forbidden
429TooManyRequests
500InternalServerError
503ServiceUnavailable

POST /v1/core/beneficiaries

Create a beneficiary (triggers asynchrono screening).

Beneficiary creation per `§B.8.2` + the API specification.3 `§D3`. Returns 202 Accepted with state `PENDING`; the screening pipeline per the API specification.3 `§D6` (sanctions + PEP + adverse-media) drives the `PENDING → VALID / MONITORED / BLOCKED` transition asynchronoly (typically seconds-to-minutes). **Destination identifiers are NOT collected at beneficiary creation** per the API specification.3 `§D3.3`. They accumulate per-transfer at `/transfers/{id}/submit` (`§B.9`); the `payoutMethods[]` array on `GET /v1/core/beneficiaries/{id}` populates as transfers complete. **Within-ctomer match.** Re-creating a beneficiary with identity attributes matching an existing record produces a second record (principal does not de-duplicate at the contract surface); within-ctomer matches surface as AML signals per `§D4.4`.

Parameters

NameInRequiredTypeDescription
XCorrelationIdHeader
XIdempotencyKeyHeader

Request body

application/json: BeneficiaryCreateRequest

Responses

StatusDescriptionSchema
202Beneficiary created in PENDING; screening initiated.application/json: BeneficiaryCreateResponse
400BadRequest
401Unauthorized
403Forbidden
409Conflict
415UnsupportedMediaType
429TooManyRequests
500InternalServerError
503ServiceUnavailable

GET /v1/core/beneficiaries/{beneficiaryId}

Read beneficiary detail (identity attributes, state, payout methods).

Beneficiary-detail read per `§B.8.4`. Includes echoed identity attributes, current state, accumulated payout-method list (masked destination identifiers per `§B.8.4.4` masking convention; full identifier never returned), and `ctomerActionExpected` UX hint per `§B.8.6`. Cross-ctomer AML signals per the API specification. Screening evidence and operator-decision rationale per `§D9.4` are **NOT surfaced**. Partner-app sees operational consequence only.

Parameters

NameInRequiredTypeDescription
BeneficiaryIdPathParam
XCorrelationIdHeader

Responses

StatusDescriptionSchema
200Beneficiary detail returned.application/json: BeneficiaryDetailResponse
401Unauthorized
403Forbidden
404NotFound
429TooManyRequests
500InternalServerError
503ServiceUnavailable

POST /v1/core/beneficiaries/{beneficiaryId}/archive

Archive a beneficiary (one-way ctomer-initiated).

Beneficiary-archive per `§B.8.5` + the API specification.3 `§D7`. State transitions to `ARCHIVED`; the beneficiary is excluded from default list views; the record is retained per regulatory retention. **One-way transition** per the API specification.3` — the ctomer cannot un-archive; re-creation produces a new beneficiary record (no inherited payout-method history; identity-resolution per `§D4` may surface `within_ctomer_match_*` AML signals). **Ctomer-stat gating.** Allowed in `VALID`, `MONITORED`, `RESTRICTED`, `BLOCKED`; rejected in `PENDING` and `CLOSED`. The wider gating is the ctomer's-record-cleanup permission preserved even when transactability is gated. **BLOCKED beneficiaries cannot be archived by the ctomer** per the API specification.3 `§D2` (BLOCKED is terminal-from-ctomer-side; operator-only-exit). Rejects with `beneficiary.archiveBlocked`.

Parameters

NameInRequiredTypeDescription
BeneficiaryIdPathParam
XCorrelationIdHeader
XIdempotencyKeyHeader

Responses

StatusDescriptionSchema
200Beneficiary archived.application/json: BeneficiaryArchiveResponse
401Unauthorized
403Forbidden
404NotFound
409Conflict
429TooManyRequests
500InternalServerError
503ServiceUnavailable

GET /v1/core/transfers

List the ctomer's transfers (summary projection).

Paginated transfer list per `§B.14.3`. Summary projection only — full detail (`confirmationChallenge`, `cancellation`, `refund`, `stateHistory`) requires per-item `GET /v1/core/transfers/{transferId}` calls. **Wider ctomer-stat gating per [C4].** Mirrors `§B.14.2.2` — `VALID`, `MONITORED`, `RESTRICTED`, `BLOCKED` permit; only `PENDING` (defensive — a PENDING ctomer cannot have transfers per `§B.6.3` quote-acceptance gate) and `CLOSED` reject. The read-access-wider carve-out per `§B.16.4` [C4] is regulator-aligned: ctomers retain visibility into their own transfers across stat transitions. **Filters.** `states` (comma-separated `TransferState` values); `createdSince` (RFC 3339 timestamp); `cursor` (opaque pagination per FM.3.10); `limit` (default 50; max 200). Default `states`: all non-terminal states pl terminal states from the last 30 days per `§B.14.3.3`.

Parameters

NameInRequiredTypeDescription
XCorrelationIdHeader
statesqueryNostringComma-separated list of `TransferState` values. Per `§B.14.3.3` default: all non-terminal states + terminal states from the last 30 days.
createdSincequeryNostringFilter to transfers created on or after this timestamp.
cursorqueryNostringOpaque pagination cursor per FM.3.10.
limitqueryNointeger

Responses

StatusDescriptionSchema
200Transfer list.application/json: TransferListResponse
400BadRequest
401Unauthorized
403Forbidden
429TooManyRequests
500InternalServerError
503ServiceUnavailable

GET /v1/core/transfers/{transferId}

Read transfer detail (state-conditional fields; re-issues confirmationChallenge).

Single-transfer detail per `§B.14.2`. Carries all state-conditional fields populated per the current `transferStat` per the `TransferDetailResponse` schema. The endpoint is the partner-app's primary mechanism for transfer-state observability — every transition documented in `§B.10.3` is observable here. **`confirmationChallenge` re-issuance per `§B.14.2.6`.** When `transferStat = validated`, the response carries a fresh `confirmationChallenge` (10-minute TTL); **the prior challenge is invalidated even if its TTL has not elapsed**. The re-issue-on-each-GET pattern means: a partner-app polling every 5 seconds while waiting for the ctomer to tap Pay produces a fresh challenge every poll — only the most-recently-issued challenge is valid. The ctomer's device builds the `/confirm` assertion ing the challenge from the most-recent GET. **Wider ctomer-stat gating per [C4].** Mirrors `/transfers` list — `VALID`, `MONITORED`, `RESTRICTED`, `BLOCKED` permit; only `PENDING` (defensive) and `CLOSED` reject. Read access wider than at money-moving endpoints. **Polling cadence guidance per `§B.14.4`.** State-aware exponential per FM.7 — 1s/2s/4s/8s in `registered` post-`/submit`; 5s steady in `validated`; 30s steady in network-in-flight states; 1s/2s/4s/5s in `NETWORK_CANCELLATION_PENDING`.

Parameters

NameInRequiredTypeDescription
TransferIdPathParam
XCorrelationIdHeader

Responses

StatusDescriptionSchema
200Transfer detail returned.application/json: TransferDetailResponse
401Unauthorized
403Forbidden
404NotFound
429TooManyRequests
500InternalServerError
503ServiceUnavailable

POST /v1/core/transfers/{transferId}/submit

Submit recipient + destination + purpose; triggers fast-check.

Transfer submission per `§B.9`. Attaches the ctomer's recipient commitments (beneficiary, payout method, purpose) to the transfer shell created at quote acceptance. Triggers the asynchrono fast-check pipeline per the API specification.1 `§D4`. **Two-step state machine on success.** 202 Accepted; transfer remains `registered` at the response; fast-check transitions asynchronoly to `validated` / `onreview` / `rejected` per `§D4.2`. Partner-app polls `GET /v1/core/transfers/{id}` (`§B.14`) with FM.7 exponential cadence. **Ctomer-stat gating (G5).** `VALID`-only per `§B.9.2.2` — tighter than `/accept` (which allows `VALID` + `MONITORED`). **Payout-method conditional exclion.** Exactly one of `payoutMethod.destinationIdentifier` (fresh method) or `payoutMethod.payoutMethodId` (existing method) MT be supplied. Supplying both rejects with `validation.payoutMethoonflict`; supplying neither rejects with `validation.destinationIdentifierMissing`. **Format-vs-substantive split per `§B.9.2.5`.** Submit-time validation is format-level only (length, character set, structural shape). Substantive validation (IBAN BBAN checksum; Confirmation of Payee name-match; phone-number format check; wallet-address checksum) is part of the asynchrono fast-check pipeline; results surface as state transitions, not synchrono rejections. **Quote-validity-window check at submit.** If `quote.expiresAt < server-time`, the endpoint returns 410 Gone with `transfer.quoteExpired` and the transfer shell transitions to `expired`.

Parameters

NameInRequiredTypeDescription
TransferIdPathParam
XCorrelationIdHeader
XIdempotencyKeyHeader

Request body

application/json: TransferSubmitRequest

Responses

StatusDescriptionSchema
202Transfer submitted. State remains `registered` at the 202 response; fast-check pipeline runs asynchronoly.application/json: TransferSubmitResponse
400BadRequest
401Unauthorized
403Forbidden
404NotFound
409Conflict
410Gone
415UnsupportedMediaType
429TooManyRequests
500InternalServerError
503ServiceUnavailable

POST /v1/core/transfers/{transferId}/cancel

Cancel a transfer (consumer-protection floor; cancellable until paid).

Transfer cancellation per `§B.11`. The substantive ctomer-protection commitment of the platform per the API specification.1 `§D9` "cancellable until paid" rule. State-conditional dispatch: - **Pre-funding active states** (`registered`, `onreview`, `validated`, `funding`): **synchrono** 200 OK; transition to `aborted`; `cancellationOutcome: ABORTED_PRE_FUNDING`; no refund (no money moved). - **`funded` state**: **synchrono** 202; transition to `canceled`; `cancellationOutcome: CANCELED_PRE_NETWORK`; PS-side refund flow per the API specification.1 `§D4` initiated asynchronoly. - **`topay` / `reqpay` states**: **asynchrono** 202; `cancellationOutcome: NETWORK_CANCELLATION_PENDING`; principal coordinates with correspondent network per the API specification.4`; final outcome (`NETWORK_CANCELLATION_SUCCESS` / `NETWORK_ALREADY_PAID` / `NETWORK_IN_PROGRESS_RETRY_ALLOWED`) observable via `§B.14` polling with the 1s/2s/4s/5s cadence per `§B.14.4`. - **`spended` state**: outcome resolves per the prior state per the API specification.4`. **Ctomer-stat gating widest among money-moving endpoints (per `§B.11.2.2` carve-out [C2]).** `VALID`, `MONITORED`, `RESTRICTED`, **`BLOCKED`** all permit; only `CLOSED` rejects. The regulatorily-protected cancellation right survives stat changes — the principal cannot retain funds for a transfer the ctomer wants to cancel jt becae the ctomer became BLOCKED post-funding. **Partner kill-switch does NOT block ctomer cancellation** per `§B.11.6` row 1 substantive elaboration — partners in `wind_down` / `blocked` cannot prevent cancellation of pre-existing transfers. **Idempotency.** Same key + same body returns the original response per FM.5. The single exception per `§B.11.2.7` is post-resolution `NETWORK_IN_PROGRESS_RETRY_ALLOWED`, which admits a fresh `/cancel` attempt with a different idempotency key.

Parameters

NameInRequiredTypeDescription
TransferIdPathParam
XCorrelationIdHeader
XIdempotencyKeyHeader

Request body

application/json: TransferCancelRequest

Responses

StatusDescriptionSchema
200Synchrono cancellation to `aborted` (pre-funding paths).application/json: TransferCancelResponse
202Asynchrono cancellation: - `funded` state: synchrono `canceled` + asynchrono refund. - `topay`/`reqpay` state: `NETWORK_CANCELLATION_PENDING` — poll `§B.14` for resolution.application/json: TransferCancelResponse
400BadRequest
401Unauthorized
403Forbidden
404NotFound
409Conflict
415UnsupportedMediaType
429TooManyRequests
500InternalServerError
502BadGateway
503ServiceUnavailable

POST /v1/core/transfers/{transferId}/confirm

Device-bound release-funds confirmation; promotes validated to funding.

Device-bound transfer confirmation per `§B.12`. The cryptographic gate on the `validated → funding` transition per the API specification.1 `§D2` + matrix v4 `TRF_AUTH_DEVICE_VERIFIED`. The request body carries a single field — a JWS Compact serialization of a device-signed assertion per the API specification.3` — and the principal performs the five-step verification per `§D5.2`. **Cryptographic verification chain.** (1) JWS signature verification against the registered public key for `device_id`; (2) registration-record ctomer-binding equality check; (3) payload-binding verification (`transfer_id`, `amount`, `currency`, `beneficiary_id`); (4) freshness + non-replay (`iat` within 60 seconds; `nonce` single-e); (5) principal-issued challenge consumption (`challenge` matches most-recent `confirmationChallenge` from `§B.14.2.6`). **On success.** Transfer transitions to `funding`; the principal allocates a `fundingSessionId` and `fundingWebviewUrl`; the partner-app opens the URL in an in-app webview per `§B.13`. **This response is the ONLY surface through which the partner-app obtains the funding-webview URL** — there is NO separate `POST /v1/core/transfers/{id}/funding` endpoint per `§B.13.1`. Re- opening a funding session after webview-URL expiry requires a fresh `/confirm` call, which itself requires a fresh device-bound assertion. This is the platform rules substantive defence per `§B.13.9`. **Ctomer-stat gating (G6).** `VALID`-only — mirrors `/submit` per `§B.12.2.2`. **Device-registration pre-conditions.** Ctomer mt have an active registered device per `§A.11`; `device.notRegistered` (412) if not. The `device_id` claim mt correspond to an active device; `device.deactivated` (412) for re-registered ctomers. **Cryptographic discipline.** RS256 + RSA-2048 minimum at v1; ES256 / EdDSA forward-watched at v1.1 per the API specification.0.4`. The Step 23 Appendix B flow B.3 wire-trace `alg: ES256` erratum is superseded by the API specification.3` and the `DeviceAssertion` schema description. **Lockout.** `device.assertionLockout` (429) on exceeding per-ctomer + per-device threshold per the API specification.1 `§D5.3` (15-minute backoff at v1).

Parameters

NameInRequiredTypeDescription
TransferIdPathParam
XCorrelationIdHeader
XIdempotencyKeyHeader

Request body

application/json: DeviceAssertion

Responses

StatusDescriptionSchema
200Device-bound assertion verified; transfer transitions to `funding`; `fundingSession` returned for `§B.13` webview flow.application/json: TransferConfirmResponse
400BadRequest
401Unauthorized
403Forbidden
404NotFound
409Conflict
412PreconditionFailed
415UnsupportedMediaType
422UnprocessableEntity
429TooManyRequests
500InternalServerError
503ServiceUnavailable

Schemas

Error

Standard error envelope per FM.6.2. Every error response es this shape. The `error.code` field is drawn from the controlled vocabulary at `§B.19` (Part-B-primary categories) and FM.6.3 (cross-cutting categories shared with Part A). The `details` shape varies by code per FM.3.9; common shapes are surfaced as named schemas (`ValidationIssue`, `CtomerStatDetails`, `QuoteExpiredDetails`, `RemediationHintDetails`, etc.).

FieldRequiredTypeDescription
errorYesobject

ValidationIssue

Per-field validation issue per FM.6.5. The summary code on the envelope is one of `validation.fieldInvalid`, `validation.fieldMissing`, `validation.bodyMalformed`, `validation.contentTypeUnsupported`; the per-field issue carries the specific issue code drawn from the Part-B-specific controlled vocabulary at `§B.19.13` and cross-cutting at `§B.19.14`.

FieldRequiredTypeDescription
fieldYesstringField path ing dotted notation for nested fields (e.g., `residenceAddress.country`); array indices e bracket notation (e.g., `middleNames[2]`).
codeYesstringSpecific per-field issue code from `§B.19.13` Part-B-specific vocabulary or `§B.19.14` cross-cutting vocabulary.
messageNostringOptional per-field diagnostic message.

RemediationHintDetails

Generic `details` shape carrying a single `remediationHint` value drawn from the App G `hint.partner_app.*` controlled vocabulary per `§B.17.3`. ed by the majority of `§B.19` error codes.

FieldRequiredTypeDescription
remediationHintNostringApp G remediation-hint identifier per `40_API_YesCash_AppG_HintsRemediation_v0_5_step25.md` §G.2 + `§B.17.3` controlled vocabulary. Examples: `retry_later`, `submit_profile_attributes`, `complete_kyc`, `contact_support`, `register_device`, `select_different_beneficiary`, `await_beneficiary_verification`.

CustomerStatusDetails

`details` shape for `ctomer.statBlocking` / `ctomer.statInsufficient` per FM.6.7 + `§B.16.5.1`. Carries the current ctomer stat and a remediation hint per App G.

FieldRequiredTypeDescription
currentStatusNoCustomerStatus
remediationHintNostring

QuoteExpiredDetails

`details` shape for `quote.expired` per `§B.19.4`. Carries the `quoteId` for partner-side logging and the `quoteExpiredAt` timestamp for ctomer-experience UX (the partner-app may surface "rate refreshed at X" messaging).

FieldRequiredTypeDescription
quoteIdNostring
quoteExpiredAtNostring
remediationHintNostring

BeneficiaryStateDetails

`details` shape for `beneficiary.stateBlocking` / `beneficiary.stateInsufficient` / `beneficiary.archived` per `§B.19.6`. Carries the current beneficiary state and remediation hint.

FieldRequiredTypeDescription
beneficiaryIdNostring
currentStateNoBeneficiaryState
remediationHintNostring

DeviceLockoutDetails

`details` shape for `device.assertionLockout` per `§B.19.9`. Surfaces the lockout-window retry hint per the API specification.1 `§D5.3`.

FieldRequiredTypeDescription
retryAfterSecondsNointeger
remediationHintNostring

PasswordPolicyRule

Password policy rule identifier. Surfaced for completeness; not emitted at any ctomer-context endpoint in this YAML (password operations are at the Auth API per `§A.6`, `§A.9`).

FieldRequiredTypeDescription

CustomerStatus

Six matrix v4 ctomer states per matrix v4 `§2` + `§B.3`. - **`PENDING`** — Ctomer record exists; identity attributes not yet fully submitted, or KYC not yet completed. Rejects all money-moving (G2 `/quotes/{id}/accept`, G5 `/transfers/{id}/submit`, G6 `/transfers/{id}/confirm`) and most read endpoints with `ctomer.statInsufficient` + remediation hint `submit_profile_attributes` or `complete_kyc`. - **`VALID`** — Eligible to transact under standard rules. Happy-path state for money-moving. Per matrix v4 `§4.1`. - **`MONITORED`** — System-accepted; operator-held transfers per matrix v4 `§4.7`. Permits quote acceptance per `§B.6.3` but rejects `/submit` / `/confirm` per fast-check gating per `§B.9.2.2` + `§B.12.2.2`. - **`RESTRICTED`** — System-accepted; ctomer-remediation expectation pending per matrix v4 `§4.5` / `§4.6`. Same money-moving posture as MONITORED. - **`BLOCKED`** — Ctomer cannot e the system for money-moving. Rejects all money-moving with `ctomer.statBlocking` + remediation hint `contact_support`. **Carve-out [C2]: permits `/transfers/{id}/cancel` (consumer-protection floor per `§B.11.2.2`). Carve-out [C4]: permits transfer-detail / transfer-list reads per `§B.14.2.2`.** - **`CLOSED`** — Terminal. Rejects all G1 – G9 endpoints. Per matrix v4 `§4.11`.

FieldRequiredTypeDescription

KycStatus

KYC lifecycle stat per `§B.2.3.4` + the API specification. Distinct from the matrix v4 `§B.16.5.2` axis-A2 KYC-stat vocabulary (which es lower-case `verified` etc.); the ctomer-context API surfaces these five values per `§B.2.3.4`. The two vocabularies are reconcilable per the `99_Stat_Enumeration_Reconciliation_Note`. - **`NOT_STARTED`** — Ctomer has not yet initiated KYC capture; the partner-app surfaces a "complete KYC" CTA. - **`IN_PROGRESS`** — A KYC session is open / resumable per `§B.4.2.5`. - **`COMPLETED`** — KYC verification succeeded; ctomer typically in `VALID` stat. - **`REJECTED`** — KYC verification failed terminally; ctomer typically in `BLOCKED` stat. - **`REMEDIATION_REQUIRED`** — KYC re-submission required per `§B.4.2.2` (`DOC_INVALID` or equivalent remediation triggers).

FieldRequiredTypeDescription

SubscriptionStatus

Partner-ctomer-relationship stat per the API specification layer) + `§B.16.5.3`. - **`active`** — Permits all ctomer-context operations. - **`spended`** — Rejects money-moving with `subscription.spended`. **Carve-out [C2]: permits `/transfers/{id}/cancel`. Carve-out [C4]: permits transfer reads.** - **`closed`** — Rejects all ctomer-context operations with `subscription.closed`.

FieldRequiredTypeDescription

TransferState

13 transfer states per the API specification.1 `§D2.1` + `§B.10.2`. **Pre-funding active states (four):** - **`registered`** — Quote accepted (`§B.6.3`) or transfer shell newly created. The fast-check pipeline (`§B.9`) has not yet completed. 120-minute timer per the API specification.3` ticking. Matrix v4 `TRF_INITIATION_QUOTE_ACCEPTED`. - **`onreview`** — Fast-check surfaced an operator-review case per the API specification. SLA target minutes-to-30-minutes per the API specification.4`. Matrix v4 `TRF_CHECK_OPERATOR_REVIEW`. - **`validated`** — Fast-check passed; the transfer is eligible for device-bound confirmation (`§B.12`). The `§B.14.2.5` `confirmationChallenge` is populated only in this state, fresh on each `GET` per `§B.14.2.6`. Matrix v4 `TRF_CHECK_PASSED`. - **`funding`** — Device-bound assertion verified; funding webview opened per `§B.12.2.7` + `§B.13`. Matrix v4 `TRF_AUTH_DEVICE_VERIFIED`. **Post-funding active states (four):** - **`funded`** — Provider confirmed funding success per the API specification.3`. PaymentSettlement (PS) recorded per the API specification. Matrix v4 `TRF_FUNDING_SUCCESS`. - **`topay`** — Correspondent network registration succeeded; offline-network correspondent confirmed payment OR open-payment network awaiting `reqpay` per the API specification. - **`reqpay`** — Open-payment network correspondent requested payment; per-network outcome pending per the API specification. - **`spended`** — Compliance event (mid-transfer ctomer or beneficiary state change) per the API specification.4`. Resolution restores to the prior state OR transitions to `rejected`. **Terminal states (five):** - **`paid`** — Recipient received funds. Happy-path terminal. - **`aborted`** — Ctomer cancelled pre-funding (any of `registered`, `onreview`, `validated`, `funding` cancelled via `§B.11`). Matrix v4 `TRF_CTOMER_ABORT_PRE_FUNDING`. - **`rejected`** — Operator or compliance team rejected per the API specification `§D4` / `§D2.4`. Terminal. - **`expired`** — 120-minute timeout from `registered` without reaching `funded` per the API specification.3`. Terminal. - **`canceled`** — Ctomer cancelled post-funding (from `funded`, `topay`, or `reqpay` per `§B.11`). Transfer-side terminal; PS state machine continues independently per the API specification. **Note on §B.16 vocabulary divergence.** `§B.16.4` and `§B.16.5.6` list a different 13-state vocabulary (`created`, `quoted`, `compliance_pending`, etc.). Per `§B.16.1` ("Where §B.16 appears to disagree with the originating section, the originating section is authoritative and §B.16 is the bug"), this YAML es the the API specification.1 `§D2.1` / `§B.10.2` vocabulary. The `§B.16` divergence is surfaced as an the API specification.3` editorial-cleanup candidate.

FieldRequiredTypeDescription

BeneficiaryState

Five beneficiary states per the API specification.3 `§D2` + `§B.16.5.5`. - **`PENDING`** — Beneficiary in compliance screening per the API specification.1` step 1. Rejects e at money-moving with `beneficiary.stateInsufficient` + remediation hint `await_beneficiary_verification`. - **`VALID`** — Screening clear; permits money-moving subject to other axes. - **`MONITORED`** — System-accepted; operator-held per the API specification.3`. Permits money-moving; operator-hold is server-side. - **`BLOCKED`** — Sanctions / PEP / adverse-media hit per the API specification. Rejects money-moving with `beneficiary.stateBlocking` + remediation hint `select_different_beneficiary`. Cannot be archived by the ctomer (operator-only exit) per `§B.8.5.2`. - **`ARCHIVED`** — Ctomer-archived per `§B.8.5`. One-way transition; re-creation produces a new beneficiary record (does not unarchive).

FieldRequiredTypeDescription

BeneficiaryRelationship

Closed-vocabulary relationship-to-ctomer per the API specification.3 `§D3.2`. eful for transaction-monitoring; `SELF` covers self-remittance.

FieldRequiredTypeDescription

PayoutMethodType

Closed payout-method enumeration at v1 per `§B.8.4.4`. Per-corridor availability is operational configuration per the API specification.3 `§D5.1`; method not configured for the quote's `corridor` returns `validation.methodNotAvailableForCorridor` (400).

FieldRequiredTypeDescription

PurposeOfTransfer

Closed-vocabulary structured AML data point per `§B.9.2.3` + FATF Rec. 16 + EU FTR 2023/1113 Article 4 + MLR 2017 reg. 64 + BSA 31 C §5318. Per-YesCash extension (e.g., state MTL codes like `RENT`, `INSURANCE`) admitted via FM.8 change-control.

FieldRequiredTypeDescription

CancellationReason

Closed-vocabulary cancellation reason per `§B.11.2.3`. Captured for fraud-pattern detection per the API specification.1 `§D6` and Consumer Duty fairness-of-outcome surveillance.

FieldRequiredTypeDescription

CancellationOutcome

Closed-vocabulary cancellation outcome per `§B.11.3`. Observable synchronoly in the `/cancel` response (for immediate-resolution paths) and asynchronoly via `§B.14` polling (for network-coordination paths).

FieldRequiredTypeDescription

RefundStatus

Ctomer-context projection of the the API specification.1 `§D2` PaymentSettlement state machine per `§B.15.2`. PS records are NOT directly exposed at v1 per the API specification projection surfaces on the transfer-detail response.

FieldRequiredTypeDescription

RefundMethod

Refund routing method per `§B.15.2`. v1 supports `ORIGINAL_PAYMENT_METHOD` only; reassignment per the API specification.1.

FieldRequiredTypeDescription

KycSessionState

KYC session lifecycle state per `§B.4.3.4`. Session-lifecycle only; KYC outcomes surface via `GET /v1/core/profile` (`kycStat`) and the `ctomer.stat_changed` webhook.

FieldRequiredTypeDescription

KycSessionPurpose

KYC session purpose per `§B.4.2.2`. Determined server-side from ctomer-stat + KYC-stat combination; not partner-supplied.

FieldRequiredTypeDescription

FundingSessionStatus

Funding-session lifecycle state per `§B.13`. Observable on the transfer-detail `fundingSession` sub-object while `transferStat = funding`.

FieldRequiredTypeDescription

IdentifierType

Identifier type per `§A.7.6`. Surfaced on the profile-read response in the identifier set.

FieldRequiredTypeDescription

Gender

Regulator-acceptable per EU AMLR identity-attribute set per `§B.2.2.3`.

FieldRequiredTypeDescription

NextStep

Partner-app navigation directive per `§B.9.5` + `§B.10.2`. Always populated on substantive ctomer-context responses; `null` on terminal-state responses.

FieldRequiredTypeDescription

CustomerActionExpected

Partner-app ctomer-experience UX hint per `§B.10.2`. Always populated on substantive ctomer-context responses (`NONE` on terminal states).

FieldRequiredTypeDescription

StructuredAddress

Structured residential or beneficiary address per `§B.2.2.3` / `§B.8.2.4`.

FieldRequiredTypeDescription
addressLine1Yesstring
addressLine2Nostring
cityYesstring
regionNostringState / province / region. Required for YesCash.
postalCodeNostring
countryYesstringISO 3166-1 alpha-3 country code.

PlaceOfBirth

Optional place-of-birth per `§B.2.2.3`. Both fields required if `placeOfBirth` is present.

FieldRequiredTypeDescription
cityYesstring
countryYesstringISO 3166-1 alpha-3.

IdentifierSummary

Per-identifier summary surfaced in the profile-read response. Same shape as the Auth API `GET /v1/auth/identifiers` row per `§A.8.2.4`.

FieldRequiredTypeDescription
identifierIdYesstring
identifierTypeYesIdentifierType
identifierMaskedYesstringMasked identifier per `§A.7.7` masking convention.
verifiedAtYesstring
canRemoveYesboolean

Corridor

Corridor metadata per the API specification.5. Per the JWS claims on the partner-signed quote per `§B.6.2.4`.

FieldRequiredTypeDescription
originCountryYesstringISO 3166-1 alpha-3 origin country.
destinationCountryYesstring
payoutMethodYesstringLower-case payout-method identifier per the corridor catalogue (e.g., `bank_account`, `cash_pickup`, `wallet_transfer`, `mobile_money`).

PayoutMethodRequest

`payoutMethod` request sub-object on `POST /v1/core/transfers/{id}/submit` per `§B.9.2.4`. Mutual exclion between `destinationIdentifier` (fresh method) and `payoutMethodId` (existing method on the beneficiary). Exactly one of the two MT be supplied; supplying both rejects with `validation.payoutMethoonflict` (400). Supplying neither rejects with `validation.destinationIdentifierMissing` (400).

FieldRequiredTypeDescription
methodTypeYesPayoutMethodType
destinationIdentifierNostringDestination identifier appropriate to `methodType` — account number (IBAN for EU; per-country format for others) for `BANK_TRANSFER`; phone number for `CASH_PICKUP` / `MOBILE_MONEY`; wallet address for `WALLET_TRANSFER`. Required if `payoutMethodId` is null. The full identifier is principal-internal post-submit; subsequent reads surface only the masked form per `§B.8.4` / `§B.9.2.7`.
payoutMethodIdNostringReference to a previoly-accumulated payout method on the same beneficiary per the API specification.3 `§D5.2`. Required if `destinationIdentifier` is null. Mt reference a non-archived method on the bound `beneficiaryId`; mismatch on `methodType` rejects with `validation.payoutMethodTypeMismatch` (400).

PayoutMethodMasked

`payoutMethod` masked surface on transfer-detail responses per `§B.9.2.6` + `§B.14.2.5`. The full `destinationIdentifier` is never returned at the ctomer-context API per the API specification.3 `§D5.4` + platform rules.

FieldRequiredTypeDescription
payoutMethodIdYesstring
methodTypeYesPayoutMethodType
corridorYesstringHyphenated origin-destination ISO 3166-1 alpha-2.
destinationIdentifierMaskedYesstringMasked representation per `§B.8.4.4` masking convention; last 4 characters for bank accounts and phone numbers; last 6 for wallet identifiers.
addedAtNostringTimestamp of first successful transfer that produced the method per the API specification.
archivedNoboolean

PayoutMethodSummary

Per-method entry in `beneficiary.payoutMethods[]` per `§B.8.4.4`. Same shape as `PayoutMethodMasked`.

FieldRequiredTypeDescription
payoutMethodIdYesstring
methodTypeYesPayoutMethodType
corridorYesstring
destinationIdentifierMaskedYesstring
addedAtYesstring
archivedYesboolean

StateHistoryEntry

Per-transition entry in `transfer.stateHistory[]` per `§B.14.2.5`.

FieldRequiredTypeDescription
stateYesTransferState
transitionedAtYesstring
reasonCodeYesstringMatrix v4 `§4.12` TRANSFER reason code (e.g., `TRF_INITIATION_QUOTE_ACCEPTED`, `TRF_CHECK_PASSED`, `TRF_AUTH_DEVICE_VERIFIED`, `TRF_FUNDING_SUCCESS`).

FundingSession

Funding-session sub-object surfaced on `/transfers/{id}/confirm` response and on the transfer-detail response while `transferStat = funding` per `§B.12.2.7` + `§B.14.2.5`.

FieldRequiredTypeDescription
fundingSessionIdYesstring
fundingWebviewUrlYesstringPrincipal-served funding webview URL on the `funding.{YesCash}.yescash.example` host. Single-e per funding attempt per `§B.13.7`; 30-minute TTL.
expiresAtYesstring30 minutes from session creation.

CancellationDetail

`cancellation` sub-object on transfer-detail response per `§B.14.2.5`. Populated when the transfer has had a `§B.11` cancellation call; `null` otherwise.

FieldRequiredTypeDescription
cancellationOutcomeNoCancellationOutcome
cancellationReasonNoCancellationReason
cancelRequestedAtNostring
canceledAtNostring
networkCancellationExpectedByNostringPopulated only while `cancellationOutcome = NETWORK_CANCELLATION_PENDING`; 60-second hint per the API specification.1 `§D7.4`.

RefundDetail

`refund` sub-object on transfer-detail response and `/cancel` response (for `funded`-state cancellations) per `§B.11.2.5` + `§B.14.2.5` + `§B.15.2`. Ctomer-context projection of the API specification.1 PaymentSettlement state; PS records are NOT directly exposed.

FieldRequiredTypeDescription
refundStatusNoRefundStatus
estimatedRefundCompletionByNostringPer-payment-method operational estimate; typically seconds for instant-refund-capable rails, minutes-to-hours for card refunds, 1–3 biness days for some methods.
refundMethodNoRefundMethod

ProfileSubmitRequest

Ctomer profile submission per `§B.2.2.3`. Triggers identity resolution per the API specification outcomes); the response shape is uniform across all three outcomes per the silent-merge defence at `§B.2.2.2`. Sanctions screening per the API specification via `GET /v1/core/profile` and the `ctomer.stat_changed` webhook.

FieldRequiredTypeDescription
firstNameYesstringPer-YesCash character set (Latin-1 pl diacritics for YesCash; ICAO 9303-aligned for KYC document matching).
lastNameYesstring
middleNamesNoarray<string>Zero-or-more middle names for ICAO 9303-aligned KYC document matching.
dateOfBirthYesstringISO 8601 date `YYYY-MM-DD`. The ctomer mt be of legal age per the YesCash's age-of-majority threshold (18 in ); under-18 rejects with `validation.fieldFormatInvalid` carrying `details.rule = "MIN_AGE_18"`.
nationalityYesstringISO 3166-1 alpha-3 nationality code. Per-YesCash comprehensive-sanctions-jurisdiction nationalities reject with `validation.nationalityNotAccepted` (400). Per-YesCash acceptance list lands in the Step 25 appendix.
residenceCountryYesstringISO 3166-1 alpha-3 country of residence. Out-of-acceptance-set residences reject with `validation.residenceCountryNotAccepted` (400). Defence-in-depth check: mt match `residenceAddress.country`.
residenceAddressYesStructuredAddress
genderNoGender
placeOfBirthNoPlaceOfBirth

ProfileSubmitResponse

Profile-submission response per `§B.2.2.4`. The shape is uniform across all three the API specification partner-app cannot distinguish Outcome 1 (confirmed match; silent merge) from Outcome 2 (confirmed non-match) from Outcome 3 (operator-review-pending). The response carries no `MasterCtomerId` per the API specification.

FieldRequiredTypeDescription
statusYesCustomerStatus
kycRequiredYesbooleanPartner-app UX convenience field. `true` after profile submission until KYC completion.
nextStepYesNextStep

ProfileReadResponse

Profile-read response per `§B.2.3.4`. The substantive ctomer-state-observation surface — consumed at ctomer-app login-success per the `§A.7` profile-fetch-then-gate pattern, at navigation to profile / stat screens, and at state refresh in response to the `ctomer.stat_changed` webhook.

FieldRequiredTypeDescription
subscriptionIdYesstringPartner-scoped `SubscriptionId` per the API specification.6`. Informational on the wire — partner-side logging / observability; not ed in subsequent URLs (Part B URLs are self-referential per `§B.1.4`).
statusYesCustomerStatus
statusOperationalHintNostringFree text from controlled vocabulary per the API specification.4` (e.g., `"document re-submission required"`, `"additional verification in progress"`). `null` when no operational hint applies. Vocabulary operationally maintained; the spec admits the field shape without enumerating the full vocabulary at v1.
kycStatusYesKycStatus
transactabilityYesbooleanPartner-app convenience boolean — `true` when the ctomer can initiate money-moving (VALID / MONITORED / RESTRICTED with `kycStat = COMPLETED`); `false` otherwise.
customerActionExpectedYesbooleanPartner-app UX hint — `true` when partner-app should surface ctomer-action CTAs (KYC re-submission; identifier re-verification; etc.); `false` for happy-path steady-state.
profileYesobjectEcho of submitted profile per `§B.2.3.4`.
identifiersYesarray<IdentifierSummary>

KycSessionCreateResponse

KYC session creation response per `§B.4.2.4`. Request body is **empty** — session purpose is determined server-side from the ctomer's KYC-lifecycle state per the API specification. The session is server-side idempotent per `§B.4.2.5` — an existing in-progress session within TTL is returned for resumability.

FieldRequiredTypeDescription
kycSessionIdYesstring
webviewUrlYesstringPrincipal-served KYC webview URL on `kyc.{YesCash}.yescash.example`. Single-e-bound to this `kycSessionId`; opaque to partner-app (do not parse / introspect).
expiresAtYesstring30 minutes from session creation; absolute TTL.
closureCallbackYesobjectClosure-callback configuration per `§B.5.3`. The partner-app es this to receive webview-closure signals via URL-scheme deep-link (mobile) or `postMessage` (web-embed).

KycSessionReadResponse

KYC session-lifecycle read per `§B.4.3.4`. Session-lifecycle only; no KYC outcome details, no verification-pipeline state, no artefact-level signal. KYC outcomes surface via `GET /v1/core/profile` (`kycStat`) and the `ctomer.stat_changed` webhook stream.

FieldRequiredTypeDescription
kycSessionIdYesstring
sessionStateYesKycSessionState
openedAtYesstring
closedAtNostringWebview-closure timestamp; `null` while `IN_PROGRESS`.
expiresAtYesstring24 hours from `openedAt` (absolute TTL distinct from the 30-minute webview-URL TTL).

QuoteCreateRequest

Quote creation request per the App B flow B.2 wire trace + `§B.6.2` / `§B.18.6` sandbox reachability surface. The partner-app re-presents the ctomer's pricing intent to the principal; the principal applies the the API specification.5 pricing envelope per `§D5` and returns a signed quote. **Note on inventory.** `§B.0.3` does not list this endpoint in the Part B inventory table; App B wire traces and `§B.18.6` sandbox reachability table treat it as load-bearing. This YAML follows App B / `§B.18.6`; the `§B.0.3` inventory gap is surfaced as an the API specification.3` editorial-cleanup candidate.

FieldRequiredTypeDescription
originAmountYesstringString-encoded decimal per FM.3.2 money-field convention (avoids floating-point precision loss). Always six decimal places.
originCurrencyYesstringISO 4217 three-letter currency code.
destinationCurrencyYesstring
beneficiaryIdYesstringCtomer's selected recipient per `§B.8`. Mt resolve in ctomer's `Subscription` scope per `§B.1.3`. Beneficiary state mt be `VALID` or `MONITORED` per `§B.16.5.5`; `PENDING` returns `beneficiary.stateInsufficient` (403); `BLOCKED` / `ARCHIVED` returns `beneficiary.stateBlocking` (403).

QuoteResponse

Signed quote response per `§B.6.2.4`. Surfaces the substantive money fields (amounts, fees, FX rate, validity window), the corridor metadata, the JWS signature for partner-side side-verification per the API specification.5 `§D3`, and the lifecycle `quoteStat`.

FieldRequiredTypeDescription
quoteIdYesstring
originAmountYesstring
originCurrencyYesstring
destinationAmountYesstring
destinationCurrencyYesstring
fxRateYesstringPer-quote FX rate per the API specification.5 pricing-envelope. Supervised against the per-corridor reference rate per the API specification envelope-breach surfaces at acceptance time via `quote.envelopeBreach`.
principalFeeYesstring
partnerFeeYesstring
totalCustomerCostYesstringTotal consumer-facing cost per the API specification.5 `§D3.3`. Surfaced verbatim in the `§B.7` disclosure text.
totalCustomerCostCurrencyYesstring
quoteValidUntilYesstringQuote-validity-window expiry per the API specification.5 `§D4`. 60-second default; 30-minute CFPB ceiling applies for -YesCash quotes.
quoteSignatureYesstringJWS Compact Serialization (RFC 7515) over the canonical quote payload per the API specification.5 `§D3`. Three base64url segments separated by dots: `<protected-header>.<payload>.<signature>`. Signed by the partner with the partner's per-YesCash RS256 private key; principal verifies at ingestion per `§D2` step 2. Surfaced to the ctomer-context API so partner-apps may side-verify if desired.
quoteStatusNostringNormalised quote-lifecycle state per `§B.6.2.4`. Computed server-side from the quote ingestion state and `expiresAt` validity-window check.
corridorYesCorridor

QuoteAcceptRequest

Quote-acceptance body per `§B.6.3`. The `disclosureToken` from `GET /v1/core/quotes/{id}/disclosure` is the sole substantive field; the ctomer cannot accept without first fetching the regulator-aligned disclosure. The disclosure-token is single-e at acceptance per `§B.7.3`. The `purposeOfTransfer` field is collected here per App B wire trace + `§B.6.3` convention (carries forward to the transfer created at acceptance).

FieldRequiredTypeDescription
disclosureTokenYesstring
purposeOfTransferYesPurposeOfTransfer

QuoteAcceptResponse

Quote-acceptance response per `§B.6.3.4`. Creates the transfer shell in `registered` state per the API specification.1 `§D2` + matrix v4 `§4.12` `TRF_INITIATION_QUOTE_ACCEPTED`. The next step is `/transfers/{id}/submit` to attach beneficiary + payout method + purpose. **Note on App B wire-trace divergence.** App B flow B.2 step 3 wire trace shows `transferState: "validated"` at acceptance. Per `§B.6.3.4` + `§B.12.5` substantive sections, acceptance creates the transfer at `registered` (not `validated`); `validated` is reached only after `/submit` triggers the fast-check pipeline per `§B.9` + the API specification. This YAML follows the substantive sections per the Step 27 Q6 convention. App B wire trace surfaced as the API specification.3` editorial candidate.

FieldRequiredTypeDescription
transferIdYesstring
transferStatusYesTransferState
quoteIdYesstring
acceptedAtYesstringServer-recorded acceptance timestamp. Substantive evidence per the API specification.5 `§D8` / `§D9`.
nextStepYesNextStepAlways `TRANSFER_CONFIRMATION_REQUIRED` at successful acceptance — directs partner-app to `/transfers/{id}/submit`.

DisclosureResponse

Regulator-aligned disclosure response per `§B.7.2.4`. The `disclosureText` is principal-authored from the Disclosure Content Catalog for the `(YesCash, language, version)` triple. The `disclosureToken` is single-e at quote acceptance per `§B.7.3`.

FieldRequiredTypeDescription
disclosureTokenYesstring
disclosureVersionYesstringPer-YesCash regulator-aligned content version.
disclosureLanguageYesstringRFC 5646 language tag echoing the actually-served locale per `§B.7.2.3` resolution order.
disclosureTextYesstringVerbatim regulator-aligned text. Plain-text with newline separators; partner-app renders with line-break preservation. Principal-authored and partner-untamperable per platform rules row 5. Includes substituted money fields per the catalog's substitution rules.
regulatoryAnchorsYesarray<string>Closed enumeration of regulatory-framework citations per `§B.7.2.4`. v1 values: - EU-ES: `PSD2_ARTICLE_44`, `PSD2_ARTICLE_45`, `PSD2_ARTICLE_46`, `RD_19_2018_TRANSPOSITION` - : `PSRS_2017_REG_43`, `PSRS_2017_SCHEDULE_4`, `_PRIN_2A`, `_FG22_5` - : `CFPB_1005_31`, `CFPB_1005_31_B_2`, `CFPB_1005_36`, `EFTA_1693`
totalConsumerCostNostringEchoed money field per `§B.7.2.4`.
sendAmountNostring
sendCurrencyNostring
receiveAmountNostring
receiveCurrencyNostring
fxRateNostring
issuedAtYesstring
expiresAtYesstring30 minutes after `issuedAt` per `§B.7.3`.

BeneficiaryCreateRequest

Beneficiary creation per `§B.8.2.3` + the API specification.3 `§D3`. Name fields per `§D3.1` required; supplementary fields per `§D3.2` optional. **Destination identifiers (account numbers / phone numbers / wallet addresses) are NOT collected at beneficiary creation** per the API specification.3 `§D3.3`; they accumulate per-transfer at `/transfers/{id}/submit`.

FieldRequiredTypeDescription
firstNameYesstring
lastNameYesstring
dateOfBirthNostringOptional per the API specification.3 `§D3.2`. Improves identity-resolution and screening match quality.
addressNoStructuredAddress
nationalityNostringISO 3166-1 alpha-2. eful for sanctions-list jurisdiction matching.
countryOfResidenceNostringISO 3166-1 alpha-2. eful for high-risk-jurisdiction screening.
relationshipToCustomerNoBeneficiaryRelationship

BeneficiaryCreateResponse

202 Accepted response per `§B.8.2`. Beneficiary created in `PENDING` state; screening pipeline per the API specification.3 `§D6` transitions to `VALID` / `MONITORED` / `BLOCKED` asynchronoly (typically seconds-to-minutes). Partner-app observes via `GET /v1/core/beneficiaries/{id}` polling or the `beneficiary.state_changed` webhook (Partner-Only spec).

FieldRequiredTypeDescription
beneficiaryIdYesstring
stateYesBeneficiaryState
createdAtYesstring

BeneficiarySummary

Per-item summary in the beneficiary-list response per `§B.8.3.4`.

FieldRequiredTypeDescription
beneficiaryIdYesstring
firstNameYesstring
lastNameYesstring
stateYesBeneficiaryState
createdAtYesstring
lastUsedAtNostringPer the API specification.3 `§D5`; `null` if the beneficiary has never been ed.
payoutMethodCountYesintegerCount of non-archived payout methods. Detail at `GET /v1/core/beneficiaries/{id}`.

BeneficiaryListResponse

Paginated list per FM.3.10. Default state filter excludes ARCHIVED.

FieldRequiredTypeDescription
itemsYesarray<BeneficiarySummary>
nextCursorNostringOpaque cursor per FM.3.10; `null` on last page.

BeneficiaryDetailResponse

Beneficiary-detail response per `§B.8.4.4`. Includes echoed identity attributes, current state, and accumulated payout-method list. Cross-ctomer AML signals per the API specification `§D9.4` are NOT surfaced — partner-app sees operational consequence only.

FieldRequiredTypeDescription
beneficiaryIdYesstring
firstNameYesstring
lastNameYesstring
dateOfBirthNostring
addressNoStructuredAddress
nationalityNostring
countryOfResidenceNostring
relationshipToCustomerNoBeneficiaryRelationship
stateYesBeneficiaryState
createdAtYesstring
stateChangedAtYesstring
lastUsedAtNostring
customerActionExpectedNostringPartner-app UX guidance keyed by state per `§B.8.6`.
payoutMethodsYesarray<PayoutMethodSummary>

BeneficiaryArchiveResponse

Archive response per `§B.8.5`. One-way transition per the API specification.3 `§D7.3` — ctomer cannot un-archive; re-creation produces a new beneficiary record (no inherited payout-method history).

FieldRequiredTypeDescription
beneficiaryIdYesstring
stateYesBeneficiaryStateAlways `ARCHIVED` on success.
archivedAtYesstring

TransferSubmitRequest

Transfer submission per `§B.9.2.3` — attaches beneficiary + payout method + purpose to the transfer shell created at quote acceptance. Triggers the asynchrono fast-check pipeline per the API specification.1 `§D4`.

FieldRequiredTypeDescription
beneficiaryIdYesstringCtomer's selected recipient per `§B.8`. Mt be in `VALID` state at submit per the API specification.3 `§D2` / the API specification.1 `§D4.1`; `PENDING`, `MONITORED`, `BLOCKED`, `ARCHIVED` reject with `beneficiary.stateBlocking` (403).
payoutMethodYesPayoutMethodRequest
purposeOfTransferYesPurposeOfTransfer

TransferSubmitResponse

202 Accepted per `§B.9.2.6`. Transfer remains in `registered` at the 202; the fast-check pipeline transitions asynchronoly to `validated` / `onreview` / `rejected` per the API specification.2`. Partner-app observes via `GET /v1/core/transfers/{id}` polling per `§B.14`.

FieldRequiredTypeDescription
transferIdYesstring
transferStatusYesTransferStateAlways `registered` at the 202 response.
beneficiaryIdYesstring
payoutMethodYesPayoutMethodMasked
purposeOfTransferYesPurposeOfTransfer
submittedAtYesstring
fastCheckExpectedByYesstringForward hint — typically `submittedAt + 5s` per the API specification sub-second-to-seconds target. Partner-app polls `GET /v1/core/transfers/{transferId}` per `§B.14` with FM.7 exponential cadence per `§B.14.4`.
nextStepYesNextStepAlways `AWAIT_FAST_CHECK` at the 202 response.

TransferCancelRequest

Transfer cancellation per `§B.11.2.3`. Ctomer-stat gating is the widest among money-moving endpoints per the consumer-protection floor at `§B.11.2.2` [C2]: `VALID`, `MONITORED`, `RESTRICTED`, **BLOCKED** all permit; only `CLOSED` rejects. Partner kill-switch does NOT block ctomer cancellation per `§B.11.6` row 1 substantive elaboration.

FieldRequiredTypeDescription
cancellationReasonYesCancellationReason

TransferCancelResponse

Cancellation response per `§B.11.2.4` (pre-funding paths; synchrono `aborted`) + `§B.11.2.5` (`funded` state; synchrono `canceled` + async refund) + `§B.11.2.6` (`topay`/`reqpay` paths; async network coordination). The response stat varies per outcome: 200 for synchrono pre-funding `aborted`; 202 for asynchrono paths and for `funded`-state `canceled` with refund initiation.

FieldRequiredTypeDescription
transferIdYesstring
transferStatusYesTransferState
cancellationOutcomeYesCancellationOutcome
canceledAtNostringPopulated when transfer reached `aborted` or `canceled` terminal; `null` while `NETWORK_CANCELLATION_PENDING`.
nextStepNoobject`null` on terminal states.
customerActionExpectedNoobject
networkCancellationExpectedByNostringPopulated only on async network-coordination paths (`NETWORK_CANCELLATION_PENDING`); 60-second hint per the API specification.1 `§D7.4`.
refundNoobjectPopulated for `funded`-state cancellation (`CANCELED_PRE_NETWORK`) and resolved network-coordination paths with refund initiation. `null` for pre-funding paths (`ABORTED_PRE_FUNDING` — no money moved).

DeviceAssertion

Device-bound transfer-confirmation assertion per `§B.12.2.3` + App C `§C.3`. The request body carries a single JWS Compact serialization signed by the ctomer's registered RSA private key; all binding to `transferId`, `amount`, `currency`, `beneficiaryId`, `deviceId`, `nonce`, `challenge`, and `iat` is inside the signed payload per the API specification.3.3`. **Cryptographic discipline.** `alg=RS256` ONLY at v1; RSA-2048 minimum modul per the API specification.0.2` + the API specification.1 `§D5.1` + FAPI 1.0 Baseline + NIST SP 800-131A. ES256 / EdDSA are forward-watched for v1.1 per the API specification.0.4`. **The Step 23 Appendix B flow B.3 step 5 wire-trace erratum** (which silently surfaced `alg: ES256`) is superseded by the API specification.3` corrective reference; v1 closes on RS256 only. **Verification chain (principal-side, the API specification.1 `§D5.2`):** (1) JWS signature verification against the registered public key for `device_id`; (2) registration-record ctomer-binding equality check (the device's `master_ctomer_id` mt match the JWT-resolved ctomer); (3) payload-binding verification (`transfer_id`, `amount`, `currency`, `beneficiary_id` match the transfer record); (4) freshness and non-replay (`iat` within 60 seconds; `nonce` single-e); (5) principal-issued challenge consumption (`challenge` matches the most-recently-issued `confirmationChallenge` from `§B.14.2.6`). On any verification-step failure, the corresponding `§B.19.9` `device.*` code is returned. The verbatim JWS is preserved per the API specification.2` evidence pattern.

FieldRequiredTypeDescription
deviceAssertionYesstringJWS Compact Serialization (RFC 7515): three base64url segments separated by dots. Header: `alg=RS256`, `kid=<device-registration kid>`, `typ=JWT`. Payload per the API specification.3.3`.

TransferConfirmResponse

Device-bound confirmation response per `§B.12.2.7`. Transitions transfer `validated → funding` per the API specification.1 `§D2` + matrix v4 `TRF_AUTH_DEVICE_VERIFIED`. Returns the principal-allocated `fundingSessionId` and `fundingWebviewUrl` for the `§B.13` funding flow. **Important: this response is the ONLY surface through which the partner-app obtains the funding-webview URL.** Per `§B.13.1`, there is NO separate `POST /v1/core/transfers/{id}/funding` endpoint. Re-opening a funding session after the prior webview's URL expires (per `§B.13.7`) requires a fresh `/confirm` call, which itself requires a fresh device-bound assertion. This is the platform rules `§B.13.9`. **Note on App B wire-trace divergence.** App B flow B.7 step 1 wire trace shows `POST /v1/core/transfers/{id}/funding` as the funding-session-opening call; `§B.19.8` references a `/transfers/{id}/funding/start` form. Per `§B.13.1` authoritative framing — "§B.13 introduces no endpoints — the funding session is initiated at §B.12 `/confirm`" — this YAML omits the `/funding` endpoint. The App B flow B.7 wire trace and `§B.19.8` text are surfaced as substantive (not editorial) the API specification.3` candidates.

FieldRequiredTypeDescription
transferIdYesstring
transferStatusYesTransferStateAlways `funding` on success.
confirmedAtYesstring
nextStepYesNextStepAlways `OPEN_FUNDING_WEBVIEW` on success.
fundingSessionYesFundingSession

TransferDetailResponse

Single-transfer detail per `§B.14.2`. Carries all state-conditional fields populated per the current `transferStat`. **State-conditional fields:** - `confirmationChallenge` + `confirmationChallengeExpiresAt`: populated ONLY when `transferStat = validated`; re-issued on each GET per `§B.14.2.6` (the prior challenge is invalidated even if its TTL has not elapsed). - `transferExpiresAt`: populated for pre-funding active states (`registered`, `onreview`, `validated`, `funding`) only; 120-minute timer from `registered` per the API specification.1 `§D2.3`. - `fundingSession`: populated ONLY when `transferStat = funding`; echoes the `/confirm` response payload per `§B.12.2.7`. - `cancellation`: populated when the transfer has had a `§B.11` cancellation call; `null` otherwise. - `refund`: populated when refund flow initiated per `§B.15`; `null` for transfers that have NOT had a refund triggered. The endpoint is also the principal's `confirmationChallenge` issuance surface — when `transferStat = validated`, each `GET` returns a fresh challenge consumed at `§B.12` `/confirm`. The re-issue-on-each-GET pattern is the substantive single-e defence per `§B.14.2.6`.

FieldRequiredTypeDescription
transferIdYesstring
transferStatusYesTransferState
transferStateChangedAtYesstring
originAmountYesstring
originCurrencyYesstring
destinationAmountYesstring
destinationCurrencyYesstring
fxRateNostring
principalFeeNostring
partnerFeeNostring
totalCustomerCostNostring
totalCustomerCostCurrencyNostring
beneficiaryIdYesstring
payoutMethodNoPayoutMethodMasked
purposeOfTransferNoPurposeOfTransfer
quoteIdNostring
createdAtYesstring
submittedAtNostring
confirmedAtNostring
transferExpiresAtNostring120-minute timer from `registered` per the API specification.1 `§D2.3`. Populated for pre-funding active states only.
nextStepNoobject
customerActionExpectedYesCustomerActionExpected
confirmationChallengeNostringPrincipal-issued challenge consumed at `§B.12` `/confirm`. Populated ONLY when `transferStat = validated`; re-issued on each GET per `§B.14.2.6`. The partner-app mt consume the challenge from the most-recent GET when building the `deviceAssertion`.
confirmationChallengeExpiresAtNostring10-minute TTL from issuance per `§B.12.3`.
fundingSessionNoobjectPopulated only when `transferStat = funding`.
cancellationNoobject
refundNoobject
stateHistoryNoarray<StateHistoryEntry>Full per-transfer state-transition history per `§B.14.2.5`. Typical transfer has < 10 transitions.

TransferSummary

Per-item summary in the transfer-list response per `§B.14.3`. Summary projection only; full detail requires per-item `GET /v1/core/transfers/{transferId}` calls.

FieldRequiredTypeDescription
transferIdYesstring
transferStatusYesTransferState
transferStateChangedAtNostring
createdAtYesstring
originAmountYesstring
originCurrencyYesstring
destinationAmountYesstring
destinationCurrencyYesstring
beneficiaryIdYesstring

TransferListResponse

Paginated transfer list per FM.3.10 + `§B.14.3.4`.

FieldRequiredTypeDescription
itemsYesarray<TransferSummary>
nextCursorNostring