Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
263 changes: 259 additions & 4 deletions mintlify/openapi.yaml

Large diffs are not rendered by default.

263 changes: 259 additions & 4 deletions openapi.yaml

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions openapi/components/schemas/quotes/ExecuteQuoteRequest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
type: object
description: >-
Optional body for executing a quote. Only needed to supply an inline Strong
Customer Authentication proof; omit the body entirely for quotes that do not
require SCA.
properties:
scaAuthorization:
$ref: ../sca/ScaAuthorization.yaml
description: >-
Optional inline Strong Customer Authentication proof. Only relevant for
customers whose provider requires SCA (e.g. EU): supply this to satisfy
the challenge in the same call once the customer has the code/assertion.
Omit it to receive the quote in `PENDING_AUTHORIZATION` with an
`scaChallenge`, then authorize separately. Ignored for customers whose
provider does not require SCA.
16 changes: 15 additions & 1 deletion openapi/components/schemas/quotes/Quote.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,17 @@ properties:
type: string
enum:
- PENDING
- PENDING_AUTHORIZATION
- PROCESSING
- COMPLETED
- FAILED
- EXPIRED
description: Current status of the quote
description: >-
Current status of the quote. `PENDING_AUTHORIZATION` occurs only for
customers whose provider requires Strong Customer Authentication (e.g.
EU): the quote carries an `scaChallenge` that must be authorized before
execution, and for realtime-funding sources `paymentInstructions` are
withheld until it is satisfied.
example: PENDING
createdAt:
type: string
Expand Down Expand Up @@ -120,3 +126,11 @@ properties:
rateDetails:
$ref: ../transactions/OutgoingRateDetails.yaml
description: Details about the rate and fees for the transaction.
scaChallenge:
$ref: ../sca/ScaChallenge.yaml
readOnly: true
description: >-
Present only while `status` is `PENDING_AUTHORIZATION`: the Strong
Customer Authentication challenge to satisfy before this quote can be
executed (or, for realtime-funding sources, before `paymentInstructions`
are issued). Omitted for customers whose provider does not require SCA.
21 changes: 21 additions & 0 deletions openapi/components/schemas/sca/ScaAuthorization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
type: object
description: >-
Proof that satisfies an `ScaChallenge`. Provide exactly one of `code` (for
`SMS_OTP` / `TOTP`) or `passkeyAssertion` (for `PASSKEY`).
properties:
code:
type:
- string
- 'null'
description: >-
The one-time code the customer received by SMS, or read from their
authenticator app. In sandbox, the code is always `123456`.
example: '123456'
passkeyAssertion:
type:
- object
- 'null'
additionalProperties: true
description: >-
Opaque WebAuthn assertion produced by the device from the challenge's
`passkeyAssertionOptions`. Required when satisfying a `PASSKEY` challenge.
51 changes: 51 additions & 0 deletions openapi/components/schemas/sca/ScaChallenge.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
type: object
description: >-
A Strong Customer Authentication challenge that must be satisfied before a
money-movement operation can complete. This object is **only present when the
customer's payment provider requires SCA** (e.g. EU customers on an e-money
provider); for customers whose provider has no such requirement it is omitted
entirely and no action is needed.


When present on a quote or transaction, authorize it by submitting an
`ScaAuthorization` proof to `POST /quotes/{quoteId}/authorize` or
`POST /transactions/{transactionId}/authorize`, or inline via the optional
`scaAuthorization` field on the originating `execute` / `transfer-out` call.
required:
- id
- expiresAt
- factor
- availableFactors
properties:
id:
type: string
description: >-
Unique identifier for this challenge. The server resolves the active
challenge from the quote or transaction being authorized, so this field
need not be supplied back; it is informational (e.g. for logging or
correlation).
example: ScaChallenge:019542f5-b3e7-1d02-0000-000000000007
Comment thread
jklein24 marked this conversation as resolved.
expiresAt:
type: string
format: date-time
description: Absolute UTC timestamp after which this challenge can no longer be authorized.
example: '2025-10-03T12:05:00Z'
factor:
$ref: ./ScaFactor.yaml
description: The factor this challenge was issued for. Defaults to `SMS_OTP`.
availableFactors:
type: array
description: The factors the customer may use to satisfy this challenge.
items:
$ref: ./ScaFactor.yaml
example:
- SMS_OTP
passkeyAssertionOptions:
type:
- object
- 'null'
additionalProperties: true
description: >-
Opaque WebAuthn assertion request options, present only when `factor` is
`PASSKEY`. Pass to the device's WebAuthn API to produce the assertion
submitted back in `ScaAuthorization.passkeyAssertion`.
13 changes: 13 additions & 0 deletions openapi/components/schemas/sca/ScaFactor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
type: string
enum:
- SMS_OTP
- TOTP
- PASSKEY
description: |
A Strong Customer Authentication factor.

| Factor | Description |
|--------|-------------|
| `SMS_OTP` | One-time code sent by SMS to the customer's verified phone. Requires no prior enrollment. |
| `TOTP` | Time-based one-time code from an authenticator app. Requires enrollment. Not valid for per-transaction challenges (cannot carry dynamic linking). |
| `PASSKEY` | WebAuthn passkey assertion. Requires enrollment. |
8 changes: 8 additions & 0 deletions openapi/components/schemas/transactions/Transaction.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,11 @@ properties:
example: 'Payment for invoice #1234'
counterpartyInformation:
$ref: ./CounterpartyInformation.yaml
scaChallenge:
$ref: ../sca/ScaChallenge.yaml
readOnly: true
description: >-
Present only while `status` is `PENDING_AUTHORIZATION`: the Strong
Customer Authentication challenge to satisfy before this transaction can
proceed. Omitted entirely for customers whose provider does not require
SCA.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ type: string
enum:
- CREATED
- PENDING
- PENDING_AUTHORIZATION
- PROCESSING
- COMPLETED
- REJECTED
Expand All @@ -15,6 +16,7 @@ description: |
|--------|-------------|
| `CREATED` | Initial lookup has been created |
| `PENDING` | Quote has been created |
| `PENDING_AUTHORIZATION` | Awaiting Strong Customer Authentication. Only occurs for customers whose provider requires SCA (e.g. EU); authorize the transaction's `scaChallenge` to proceed. |
| `PROCESSING` | Funding has been received and payment initiated |
| `COMPLETED` | Cross border payment has been received, converted and payment has been sent to the offramp network |
| `REJECTED` | Receiving institution or wallet rejected payment, payment has been refunded |
Expand Down
9 changes: 9 additions & 0 deletions openapi/components/schemas/transfers/TransferOutRequest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,12 @@ properties:
Amount in the smallest unit of the currency (e.g., cents for USD/EUR,
satoshis for BTC)
example: 12550
scaAuthorization:
$ref: ../sca/ScaAuthorization.yaml
description: >-
Optional inline Strong Customer Authentication proof. Only relevant for
customers whose provider requires SCA (e.g. EU): supply this to satisfy
the challenge in the same call once the customer has the code/assertion.
Omit it on the first call to receive the transaction in
`PENDING_AUTHORIZATION` with an `scaChallenge`, then authorize separately.
Ignored for customers whose provider does not require SCA.
10 changes: 10 additions & 0 deletions openapi/openapi.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions openapi/paths/quotes/quotes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,18 @@ post:
exchangeRate: 0.92
feesIncluded: 10
transactionId: Transaction:019542f5-b3e7-1d02-0000-000000000005
'202':
description: >
Quote created but awaiting Strong Customer Authentication. Returned only
for customers whose provider requires SCA (e.g. EU) on a realtime-funding
source: the quote has status `PENDING_AUTHORIZATION` and carries an
`scaChallenge`, and `paymentInstructions` are **withheld** until the
challenge is authorized via `POST /quotes/{quoteId}/authorize`. Once
authorized, the quote's `paymentInstructions` are populated.
content:
application/json:
schema:
$ref: ../../components/schemas/quotes/Quote.yaml
'400':
description: Bad request - Missing or invalid parameters
content:
Expand Down
74 changes: 74 additions & 0 deletions openapi/paths/quotes/quotes_{quoteId}_authorize.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
parameters:
- name: quoteId
in: path
description: The unique identifier of the quote whose SCA challenge is being authorized.
required: true
schema:
type: string
example: Quote:019542f5-b3e7-1d02-0000-000000000006
post:
summary: Authorize a quote's SCA challenge
description: |
Satisfy the Strong Customer Authentication challenge carried by a quote in
`PENDING_AUTHORIZATION` status by submitting an `ScaAuthorization` proof.

This is used for realtime-funding quotes: the quote is returned with an
`scaChallenge` and **without** `paymentInstructions`; once authorized, the
quote advances and its `paymentInstructions` are populated so the customer
can fund the transfer.

This endpoint is only meaningful for customers whose payment provider
requires SCA (e.g. EU customers). For customers whose provider has no such
requirement, this returns `409`.

In sandbox, the SMS/TOTP code is always `123456`.
operationId: authorizeQuote
tags:
- Strong Customer Authentication
security:
- BasicAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: ../../components/schemas/sca/ScaAuthorization.yaml
responses:
'200':
description: Challenge authorized; the updated quote is returned.
content:
application/json:
schema:
$ref: ../../components/schemas/quotes/Quote.yaml
'400':
description: Invalid or expired authorization proof
content:
application/json:
schema:
$ref: ../../components/schemas/errors/Error400.yaml
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: ../../components/schemas/errors/Error401.yaml
'404':
description: Quote not found
content:
application/json:
schema:
$ref: ../../components/schemas/errors/Error404.yaml
'409':
description: >-
The customer's payment provider does not require SCA, or the quote has
no pending challenge to authorize.
content:
application/json:
schema:
$ref: ../../components/schemas/errors/Error409.yaml
'500':
description: Internal service error
content:
application/json:
schema:
$ref: ../../components/schemas/errors/Error500.yaml
Comment thread
jklein24 marked this conversation as resolved.
19 changes: 17 additions & 2 deletions openapi/paths/quotes/quotes_{quoteId}_execute.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,27 @@ post:
schema:
type: string
example: eyJwdWJsaWNLZXkiOiIwMmExYjIuLi4iLCJzY2hlbWUiOiJTSUdOQVRVUkVfU0NIRU1FX1RLX0FQSV9QMjU2Iiwic2lnbmF0dXJlIjoiMzA0NTAyMjEwMC4uLiJ9
requestBody:
required: false
content:
application/json:
schema:
$ref: ../../components/schemas/quotes/ExecuteQuoteRequest.yaml
responses:
'200':
description: >
Quote confirmed successfully. The transfer has been initiated and
Quote confirmed successfully. The transfer has been initiated and the
quote status has been updated.

the quote status has been updated.

For customers whose provider requires Strong Customer Authentication
(e.g. EU): supplying `scaAuthorization` **upfront on this call** satisfies
the challenge in one shot and avoids the pending state. Without it, the
quote comes back with status `PENDING_AUTHORIZATION` and an
`scaChallenge`; from that point the **only** way to release the transfer
is `POST /transactions/{transactionId}/authorize` for the quote's
`transactionId` (re-calling `execute` returns 409). The inline
`scaAuthorization` field is therefore for the initial call only.
content:
application/json:
schema:
Expand Down
Loading
Loading