Add stablecoin direct mint/burn issuance API surface#687
Conversation
Adds the public API surface for direct stablecoin issuer operations that
shipped in the Grid server (webdev #29077 mint, #29078 burn): register a
provider-created stablecoin, list/get stablecoins, create direct mint and
burn operations, and list/get the resulting issuer operations.
- New paths: /stablecoins, /stablecoins/{id}, /stablecoins/{id}/mints,
/stablecoins/{id}/burns, /stablecoins/{id}/operations,
/stablecoin-operations/{id}.
- New schemas under components/schemas/stablecoins: Stablecoin,
StablecoinListResponse, StablecoinRegisterRequest, StablecoinMintRequest,
StablecoinBurnRequest, mint/burn source+destination, StablecoinOperation,
StablecoinOperation{Type,Status,Destination,ListResponse},
StablecoinFundingInstructions, StablecoinEstimatedDelivery,
StablecoinNetwork, Stablecoin{Grid,}OperationsStatus, StablecoinIssuanceStatus.
- Adds Error503 (SERVICE_UNAVAILABLE) used by the issuance responses.
StablecoinOperation.destination is a single merged StablecoinOperationDestination
object (superset of the mint/burn request destinations), NOT a oneOf: a
non-discriminated oneOf[Mint,Burn] is ambiguous (a burn destination validates
as both variants), so the generated SDK raises "Multiple matches found" on
every burn operation response. The merged object deserializes unambiguously.
This supersedes the quote-based issuance design in #578 (which is being
closed); the shipped server implements direct operations, not quotes.
Bundled with redocly; `redocly lint` passes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
✱ Stainless preview builds for gridThis PR will update the cli go kotlin openapi php python ruby typescript Edit this comment to update them. They will appear in their respective SDK's changelogs. ✅ grid-typescript studio · code · diff
✅ grid-ruby studio · code · diff
✅ grid-go studio · code · diff
✅ grid-kotlin studio · code · diff
✅ grid-php studio · code · diff
✅ grid-openapi studio · code · diff
✅ grid-cli studio · code · diff
✅ grid-python studio · code · diff
This comment is auto-generated by GitHub Actions and is automatically kept up to date as you push. |
Greptile SummaryThis PR adds the public OpenAPI surface for direct stablecoin issuer mint/burn operations, filling a gap where the server implementation existed but the API spec (and thus generated SDKs) did not. It introduces six new path files, ~20 new schema files, and a new
Confidence Score: 4/5The new API surface is additive and well-structured; the main concern is that discriminated request schemas don't machine-enforce field requirements that the prose describes. The path and schema work is thorough — idempotency keys are present on all write operations, error codes (including 503) are correctly applied, and the merged destination design is sensibly justified. The polymorphic source/funding schemas describe type-conditional required fields in prose only, meaning SDK validators accept requests that omit required fields for specific types, pushing failures to server runtime rather than client validation. StablecoinMintFundingSource.yaml and StablecoinBurnSource.yaml for the conditional-required gaps; StablecoinFundingInstructions.yaml and StablecoinEstimatedDelivery.yaml for the fully open schema design.
|
| Filename | Overview |
|---|---|
| openapi/components/schemas/stablecoins/StablecoinMintFundingSource.yaml | Defines mint funding source variants; conditionally required fields (e.g. externalAccountId for ACH types) are described in prose but not enforced by schema constraints, generating fully optional SDK fields |
| openapi/components/schemas/stablecoins/StablecoinOperation.yaml | Response schema for a stablecoin issuer operation; mixes fundingSource (mint) and source (burn) as separate optional fields, inconsistent with the merged destination design; otherwise well-structured with appropriate required fields |
| openapi/components/schemas/stablecoins/StablecoinOperationDestination.yaml | Merged destination superset schema, well-explained design decision to avoid non-discriminated oneOf ambiguity; cleanly structured |
| openapi/components/schemas/stablecoins/StablecoinFundingInstructions.yaml | Fully open schema (additionalProperties: true, no properties declared) despite having stable known fields in the example; generates opaque SDK types; same issue in StablecoinEstimatedDelivery.yaml |
| openapi/paths/stablecoins/stablecoins_{stablecoinId}_mints.yaml | POST /stablecoins/{stablecoinId}/mints endpoint; correctly requires Idempotency-Key header, includes 201/400/401/404/409/500/503 responses; well-formed |
| openapi/paths/stablecoins/stablecoins_{stablecoinId}_burns.yaml | POST /stablecoins/{stablecoinId}/burns endpoint; mirrors mint endpoint structure, includes 503 for provider unavailability; well-formed |
| openapi/components/schemas/stablecoins/Stablecoin.yaml | New Stablecoin entity schema; required fields are well-chosen, references existing provider enums, clean |
| openapi/components/schemas/stablecoins/StablecoinBurnSource.yaml | Burn source variants; externalAccountId is required for EXTERNAL_ACCOUNT type but not enforced by schema — same conditional-required issue as StablecoinMintFundingSource |
| openapi/components/schemas/errors/Error503.yaml | New 503 SERVICE_UNAVAILABLE error schema; consistent with other error schema patterns in the repo |
| openapi/openapi.yaml | Registers six new path references for the stablecoin issuance surface; tag description updated; no issues |
Sequence Diagram
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant C as API Client
participant G as Grid API
participant P as Stablecoin Provider (Brale)
C->>G: POST /stablecoins (register, Idempotency-Key)
G->>P: Link token metadata
G-->>C: 201 Stablecoin (issuanceStatus: PROVISIONING)
C->>G: "GET /stablecoins/{stablecoinId}"
G-->>C: 200 Stablecoin (issuanceStatus: PROVISIONED)
C->>G: "POST /stablecoins/{id}/mints (Idempotency-Key)"
G->>P: Create mint operation
alt Wire-funded
G-->>C: 201 StablecoinOperation (status: PENDING_FUNDING, fundingInstructions)
P-->>G: Funds received callback
G-->>C: GET operation COMPLETED
else ACH-funded
G-->>C: 201 StablecoinOperation (status: PENDING_PROVIDER)
P-->>G: Mint confirmed
G-->>C: GET operation COMPLETED
end
C->>G: "POST /stablecoins/{id}/burns (Idempotency-Key)"
G->>P: Create burn/redemption operation
alt External Spark source
G-->>C: 201 StablecoinOperation (status: PENDING_FUNDING, fundingInstructions)
else Provider internal balance
G-->>C: 201 StablecoinOperation (status: PENDING_PROVIDER)
end
P-->>G: Burn confirmed + fiat payout
G-->>C: "GET /stablecoin-operations/{opId} COMPLETED"
C->>G: "GET /stablecoins/{id}/operations"
G-->>C: 200 StablecoinOperationListResponse (paginated)
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant C as API Client
participant G as Grid API
participant P as Stablecoin Provider (Brale)
C->>G: POST /stablecoins (register, Idempotency-Key)
G->>P: Link token metadata
G-->>C: 201 Stablecoin (issuanceStatus: PROVISIONING)
C->>G: "GET /stablecoins/{stablecoinId}"
G-->>C: 200 Stablecoin (issuanceStatus: PROVISIONED)
C->>G: "POST /stablecoins/{id}/mints (Idempotency-Key)"
G->>P: Create mint operation
alt Wire-funded
G-->>C: 201 StablecoinOperation (status: PENDING_FUNDING, fundingInstructions)
P-->>G: Funds received callback
G-->>C: GET operation COMPLETED
else ACH-funded
G-->>C: 201 StablecoinOperation (status: PENDING_PROVIDER)
P-->>G: Mint confirmed
G-->>C: GET operation COMPLETED
end
C->>G: "POST /stablecoins/{id}/burns (Idempotency-Key)"
G->>P: Create burn/redemption operation
alt External Spark source
G-->>C: 201 StablecoinOperation (status: PENDING_FUNDING, fundingInstructions)
else Provider internal balance
G-->>C: 201 StablecoinOperation (status: PENDING_PROVIDER)
end
P-->>G: Burn confirmed + fiat payout
G-->>C: "GET /stablecoin-operations/{opId} COMPLETED"
C->>G: "GET /stablecoins/{id}/operations"
G-->>C: 200 StablecoinOperationListResponse (paginated)
Prompt To Fix All With AI
Fix the following 4 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 4
openapi/components/schemas/stablecoins/StablecoinMintFundingSource.yaml:1-29
**Conditionally required fields not enforced by schema**
The description says "`externalAccountId` is required" when `type` is `ACH_DEBIT` or `SAME_DAY_ACH_DEBIT`, but no schema constraint backs this up — all sibling fields are unconstrained optional. Since this is OAS 3.1.0, `if`/`then` or `oneOf` can enforce the invariant. Without it, SDK generators produce all-optional fields, and a client can omit `externalAccountId` for an ACH_DEBIT request and the schema will still validate, pushing the error to runtime on the server side.
The same pattern applies to `StablecoinBurnSource` (`externalAccountId` required for `EXTERNAL_ACCOUNT`), `StablecoinMintDestination` (`externalAccountId` required for `EXTERNAL_ACCOUNT`, `accountId` for `GRID_INTERNAL_ACCOUNT`), and `StablecoinBurnDestination`.
### Issue 2 of 4
openapi/components/schemas/stablecoins/StablecoinFundingInstructions.yaml:1-8
**Fully open schema generates opaque SDK types**
Both `StablecoinFundingInstructions` and `StablecoinEstimatedDelivery` are defined as `type: object` with `additionalProperties: true` and no `properties`. The example shows stable, concrete fields (`rail`, `network`, `address`, `valueType` for funding; `rail`, `amount`, `currency`, `timing` for estimated delivery), yet they aren't declared as typed properties. SDK generators will produce raw `object`/`dict` types, stripping clients of any field discovery or type safety. Declaring the known fields as typed properties (and keeping `additionalProperties: true` for forward-compatibility) would give consumers something concrete without breaking unknown-field handling.
### Issue 3 of 4
openapi/paths/stablecoins/stablecoins_{stablecoinId}_operations.yaml:8-56
**No `operationType` filter on the operations list**
`listStablecoinOperations` returns both mints and burns but offers no way to filter by `operationType` (`MINT` | `BURN`). Issuers who want to see only one type (e.g., display a burn history) must client-side filter paginated results. Adding an optional `operationType` query parameter with the `StablecoinOperationType` enum would close this gap without breaking existing callers.
### Issue 4 of 4
openapi/components/schemas/stablecoins/StablecoinOperation.yaml:38-46
**Asymmetric source field naming on the response object**
`StablecoinOperation` uses `fundingSource` (typed `StablecoinMintFundingSource`) for mint operations and a separate `source` field (typed `StablecoinBurnSource`) for burn operations — two optionally-present sibling fields backed by different schemas. The PR merged the destination into a single `StablecoinOperationDestination` to avoid a non-discriminated `oneOf`, but a parallel approach on the source side was not taken. Clients inspecting a returned operation must check `operationType` and then switch between `fundingSource` and `source`, while the destination always comes from one field. A single merged `StablecoinOperationSource` would give the same unambiguous deserialization property as the destination.
Reviews (1): Last reviewed commit: "Add stablecoin direct mint/burn issuance..." | Re-trigger Greptile
| type: object | ||
| required: | ||
| - type | ||
| properties: | ||
| type: | ||
| type: string | ||
| enum: | ||
| - WIRE | ||
| - ACH_DEBIT | ||
| - SAME_DAY_ACH_DEBIT | ||
| - GRID_INTERNAL_ACCOUNT | ||
| - PROVIDER_INTERNAL_BALANCE | ||
| description: Funding source variant. For `ACH_DEBIT` and `SAME_DAY_ACH_DEBIT`, `externalAccountId` is required. Grid internal account and provider internal balance funding are reserved for follow-up support. | ||
| externalAccountId: | ||
| type: string | ||
| description: Grid `ExternalAccount` used as the ACH debit funding account. | ||
| example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000101 | ||
| accountId: | ||
| type: string | ||
| description: Grid internal funding account id for future Grid-funded mint flows. | ||
| example: InternalAccount:019542f5-b3e7-1d02-0000-000000000102 | ||
| sourceTokenIdentifier: | ||
| type: string | ||
| description: Provider token/value type for future provider internal balance funding. | ||
| example: USDC | ||
| cryptoNetwork: | ||
| type: string | ||
| description: Source crypto network for future provider internal balance funding. | ||
| example: SOLANA |
There was a problem hiding this comment.
Conditionally required fields not enforced by schema
The description says "externalAccountId is required" when type is ACH_DEBIT or SAME_DAY_ACH_DEBIT, but no schema constraint backs this up — all sibling fields are unconstrained optional. Since this is OAS 3.1.0, if/then or oneOf can enforce the invariant. Without it, SDK generators produce all-optional fields, and a client can omit externalAccountId for an ACH_DEBIT request and the schema will still validate, pushing the error to runtime on the server side.
The same pattern applies to StablecoinBurnSource (externalAccountId required for EXTERNAL_ACCOUNT), StablecoinMintDestination (externalAccountId required for EXTERNAL_ACCOUNT, accountId for GRID_INTERNAL_ACCOUNT), and StablecoinBurnDestination.
Prompt To Fix With AI
This is a comment left during a code review.
Path: openapi/components/schemas/stablecoins/StablecoinMintFundingSource.yaml
Line: 1-29
Comment:
**Conditionally required fields not enforced by schema**
The description says "`externalAccountId` is required" when `type` is `ACH_DEBIT` or `SAME_DAY_ACH_DEBIT`, but no schema constraint backs this up — all sibling fields are unconstrained optional. Since this is OAS 3.1.0, `if`/`then` or `oneOf` can enforce the invariant. Without it, SDK generators produce all-optional fields, and a client can omit `externalAccountId` for an ACH_DEBIT request and the schema will still validate, pushing the error to runtime on the server side.
The same pattern applies to `StablecoinBurnSource` (`externalAccountId` required for `EXTERNAL_ACCOUNT`), `StablecoinMintDestination` (`externalAccountId` required for `EXTERNAL_ACCOUNT`, `accountId` for `GRID_INTERNAL_ACCOUNT`), and `StablecoinBurnDestination`.
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
would it be possible to use a similar pattern to quotes here as well? the one of pattern would give us that schema level enforcement
There was a problem hiding this comment.
Yes, the quotes pattern works well here and would be cleaner than if/then. Since type already acts as a natural discriminator and the variants have non-overlapping field requirements (unlike the StablecoinOperationDestination response case mentioned in the PR description), there's no "multiple matches" ambiguity risk.
The pattern would be:
StablecoinMintFundingSource.yaml (becomes the oneOf wrapper):
oneOf:
- $ref: ./StablecoinWireFundingSource.yaml
- $ref: ./StablecoinAchDebitFundingSource.yaml
- $ref: ./StablecoinSameDayAchDebitFundingSource.yaml
- $ref: ./StablecoinGridInternalFundingSource.yaml
- $ref: ./StablecoinProviderBalanceFundingSource.yaml
discriminator:
propertyName: type
mapping:
WIRE: ./StablecoinWireFundingSource.yaml
ACH_DEBIT: ./StablecoinAchDebitFundingSource.yaml
SAME_DAY_ACH_DEBIT: ./StablecoinSameDayAchDebitFundingSource.yaml
GRID_INTERNAL_ACCOUNT: ./StablecoinGridInternalFundingSource.yaml
PROVIDER_INTERNAL_BALANCE: ./StablecoinProviderBalanceFundingSource.yamlStablecoinAchDebitFundingSource.yaml (example variant):
allOf:
- $ref: ./StablecoinMintFundingSourceBase.yaml
- type: object
required:
- type
- externalAccountId
properties:
type:
type: string
enum:
- ACH_DEBIT
externalAccountId:
type: string
description: Grid `ExternalAccount` used as the ACH debit funding account.
example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000101This same structure applies to StablecoinBurnSource and the destination schemas — since all of them use a type field with mutually exclusive enum values, the discriminator ensures exactly one variant matches, and SDK generators will mark externalAccountId as required only for the ACH variants. The base schema holds the type property definition shared across all variants.
The one difference from the StablecoinOperationDestination case (which was kept as a merged object) is that these are request schemas, so the discriminator drives serialization rather than deserialization — no ambiguity risk.
Tip: You can customize Greptile's behavior for this repo with .greptile/rules.md and .greptile/config.json.
| get: | ||
| summary: List stablecoin issuer operations | ||
| description: List issuer mint and burn operations for a stablecoin, most recent first, with cursor pagination. | ||
| operationId: listStablecoinOperations | ||
| tags: | ||
| - Stablecoins | ||
| security: | ||
| - BasicAuth: [] | ||
| parameters: | ||
| - name: limit | ||
| in: query | ||
| description: Maximum number of results to return (default 20, max 100) | ||
| required: false | ||
| schema: | ||
| type: integer | ||
| minimum: 1 | ||
| maximum: 100 | ||
| default: 20 | ||
| - name: cursor | ||
| in: query | ||
| description: Opaque cursor returned as `nextCursor` from the previous response. | ||
| required: false | ||
| schema: | ||
| type: string | ||
| responses: | ||
| '200': | ||
| description: Successful operation | ||
| content: | ||
| application/json: | ||
| schema: | ||
| $ref: ../../components/schemas/stablecoins/StablecoinOperationListResponse.yaml | ||
| '401': | ||
| description: Unauthorized | ||
| content: | ||
| application/json: | ||
| schema: | ||
| $ref: ../../components/schemas/errors/Error401.yaml | ||
| '404': | ||
| description: Stablecoin not found | ||
| content: | ||
| application/json: | ||
| schema: | ||
| $ref: ../../components/schemas/errors/Error404.yaml | ||
| '500': | ||
| description: Internal service error | ||
| content: | ||
| application/json: | ||
| schema: | ||
| $ref: ../../components/schemas/errors/Error500.yaml |
There was a problem hiding this comment.
No
operationType filter on the operations list
listStablecoinOperations returns both mints and burns but offers no way to filter by operationType (MINT | BURN). Issuers who want to see only one type (e.g., display a burn history) must client-side filter paginated results. Adding an optional operationType query parameter with the StablecoinOperationType enum would close this gap without breaking existing callers.
Prompt To Fix With AI
This is a comment left during a code review.
Path: openapi/paths/stablecoins/stablecoins_{stablecoinId}_operations.yaml
Line: 8-56
Comment:
**No `operationType` filter on the operations list**
`listStablecoinOperations` returns both mints and burns but offers no way to filter by `operationType` (`MINT` | `BURN`). Issuers who want to see only one type (e.g., display a burn history) must client-side filter paginated results. Adding an optional `operationType` query parameter with the `StablecoinOperationType` enum would close this gap without breaking existing callers.
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| fundingSource: | ||
| $ref: StablecoinMintFundingSource.yaml | ||
| source: | ||
| $ref: StablecoinBurnSource.yaml | ||
| fundingInstructions: | ||
| $ref: StablecoinFundingInstructions.yaml | ||
| destination: | ||
| $ref: StablecoinOperationDestination.yaml | ||
| estimatedDelivery: |
There was a problem hiding this comment.
Asymmetric source field naming on the response object
StablecoinOperation uses fundingSource (typed StablecoinMintFundingSource) for mint operations and a separate source field (typed StablecoinBurnSource) for burn operations — two optionally-present sibling fields backed by different schemas. The PR merged the destination into a single StablecoinOperationDestination to avoid a non-discriminated oneOf, but a parallel approach on the source side was not taken. Clients inspecting a returned operation must check operationType and then switch between fundingSource and source, while the destination always comes from one field. A single merged StablecoinOperationSource would give the same unambiguous deserialization property as the destination.
Prompt To Fix With AI
This is a comment left during a code review.
Path: openapi/components/schemas/stablecoins/StablecoinOperation.yaml
Line: 38-46
Comment:
**Asymmetric source field naming on the response object**
`StablecoinOperation` uses `fundingSource` (typed `StablecoinMintFundingSource`) for mint operations and a separate `source` field (typed `StablecoinBurnSource`) for burn operations — two optionally-present sibling fields backed by different schemas. The PR merged the destination into a single `StablecoinOperationDestination` to avoid a non-discriminated `oneOf`, but a parallel approach on the source side was not taken. Clients inspecting a returned operation must check `operationType` and then switch between `fundingSource` and `source`, while the destination always comes from one field. A single merged `StablecoinOperationSource` would give the same unambiguous deserialization property as the destination.
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Enforce conditionally-required fields, type the open schemas, add an
operations filter, and make operation source naming symmetric.
- StablecoinMintFundingSource, StablecoinBurnSource, and
StablecoinMintDestination now use the quotes-style oneOf + `type`
discriminator with per-variant schemas, so required fields (e.g.
externalAccountId for ACH_DEBIT / EXTERNAL_ACCOUNT) are enforced by
the schema instead of only being described in prose.
StablecoinBurnDestination already unconditionally requires all its
fields (single variant), so it is left as-is.
- StablecoinFundingInstructions declares its stable fields (rail,
network, address, valueType) as typed properties while keeping
additionalProperties for rail-specific passthrough, with a comment
explaining why it stays open. StablecoinEstimatedDelivery is fully
typed (rail, amount, currency, timing).
- StablecoinEstimatedDelivery.amount is now expressed in the currency's
smallest unit (minor units) to match the rest of the API's money
fields.
- GET /stablecoins/{stablecoinId}/operations gains an optional
operationType query filter.
- StablecoinOperation now reports source via a single merged
StablecoinOperationSource field (mirroring StablecoinOperationDestination)
instead of asymmetric fundingSource/source fields.
Address shreyav review on the stablecoin issuance spec: represent internal and external accounts as one `account` reference instead of an internal/external discriminator, matching the existing AccountDestination / AccountQuoteSource / AccountTransactionDestination pattern where the id prefix (`ExternalAccount:` / `InternalAccount:`) disambiguates. - StablecoinMintDestination: collapse the oneOf + type=EXTERNAL_ACCOUNT|GRID_INTERNAL_ACCOUNT discriminator (and its StablecoinExternalAccountMintDestination / StablecoinGridInternalMintDestination / StablecoinMintDestinationBase variants) into a single object with one required `accountId`. Also removes the conditionally-required-fields concern since a single always-required field has no conditional case. - StablecoinOperationDestination: merge externalAccountId/accountId into a single `accountId` and drop the now-redundant external/internal `type` (the id prefix carries it). Keeps the flat, non-oneOf merged shape; `rail` still distinguishes burn (fiat payout) from mint destinations. Regenerated openapi.yaml and mintlify/openapi.yaml via redocly bundle.
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
What
Adds the public API surface for direct stablecoin issuer operations that shipped in the Grid server (webdev #29077 mint, #29078 burn). Upstream
maincurrently has only the stablecoin provider-account surface (from #594); the mint/burn/registration surface lives only in webdev's vendoredgrid-api/openapi.yamland is absent here — so it gets clobbered on the nextupdate_schema.shregen and external SDK consumers never receive it.Surface added
/stablecoins,/stablecoins/{stablecoinId},/stablecoins/{stablecoinId}/mints,/burns,/operations,/stablecoin-operations/{stablecoinOperationId}.components/schemas/stablecoins/):Stablecoin,StablecoinListResponse,StablecoinRegisterRequest,StablecoinMintRequest,StablecoinBurnRequest, mint/burn source + destination,StablecoinOperation,StablecoinOperation{Type,Status,Destination,ListResponse},StablecoinFundingInstructions,StablecoinEstimatedDelivery,StablecoinNetwork,Stablecoin{Grid,}OperationsStatus,StablecoinIssuanceStatus.Error503(SERVICE_UNAVAILABLE) used by the issuance responses.Note on
StablecoinOperation.destinationIt is a single merged
StablecoinOperationDestinationobject (superset of the mint/burn request destinations), not aoneOf. A non-discriminatedoneOf[Mint,Burn]is ambiguous — a burn destination validates as both variants — so the generated SDK raises "Multiple matches found" on every burn operation response. The merged object deserializes unambiguously.Supersedes #578
#578 modeled issuance as quotes (
/quotes+execute); the shipped server implements direct mint/burn operations. This PR reflects what shipped. #578 is being closed.Validation
Built with
npm run build:openapi(redocly bundle) andredocly lintpasses. Draft pending review; a follow-up regenerates webdev's vendored client from this once merged.🤖 Generated with Claude Code