From 800e942e5e7b4dd9757bae6094ed33f3bac4f050 Mon Sep 17 00:00:00 2001 From: alchemy-bot <80712764+alchemy-bot@users.noreply.github.com> Date: Tue, 15 Sep 2026 12:00:14 +0000 Subject: [PATCH 1/4] [docs-agent] Add Solana Trader API docs (REST spec, overview, nav) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a new Solana Trader API surface under Chains > Solana with three operations: * GET /order — swap quote plus optional assembled base64 transaction when a taker is supplied. * GET /build — raw swap instructions for composing into your own transaction. * POST /quote-multiple-output-mints — quote a single input mint against up to 32 candidate output mints in one call. Spec: src/openapi/solana-trader/solana-trader.yaml, OpenAPI 3.1 modeled on src/openapi/prices/prices.yaml. Server https://solana-mainnet.g.alchemy.com/v2 with {apiKey} in the path (docs-demo default). Introduces x-compute-units and x-rate-limit-cus on each operation (100 placeholders), the first REST spec in this repo to carry those extensions. Overview: content/api-reference/solana/solana-trader-api-overview.mdx patterned after solana-jito-bundles-overview.mdx (not the historical Photon nft-api location). Nav slot in content/docs.yml placed between Solana Photon API and Solana Jito Bundles and Transactions, with flattened: true so method pages nest under the overview. Also adds a # Solana: Trader API block in content/api-reference/pricing-resources/pricing/compute-unit-costs.mdx between the Photon and Jito blocks (100 CU / 100 throughput placeholders), and a Related APIs entry on content/api-reference/solana/solana-api-overview.mdx. Refs DOCS-227 --- .../pricing/compute-unit-costs.mdx | 12 + .../solana/solana-api-overview.mdx | 1 + .../solana/solana-trader-api-overview.mdx | 47 ++ content/docs.yml | 7 + src/openapi/solana-trader/solana-trader.yaml | 584 ++++++++++++++++++ 5 files changed, 651 insertions(+) create mode 100644 content/api-reference/solana/solana-trader-api-overview.mdx create mode 100644 src/openapi/solana-trader/solana-trader.yaml diff --git a/content/api-reference/pricing-resources/pricing/compute-unit-costs.mdx b/content/api-reference/pricing-resources/pricing/compute-unit-costs.mdx index b84d94385..d2808a32b 100644 --- a/content/api-reference/pricing-resources/pricing/compute-unit-costs.mdx +++ b/content/api-reference/pricing-resources/pricing/compute-unit-costs.mdx @@ -226,6 +226,18 @@ For more details, check out the [Compute Units](/docs/reference/compute-units#wh | getValidityProofV2 | 1200 | 500 | {/* cu:auto end */} +# Solana: Trader API + +[Solana Trader API](/docs/chains/solana/solana-trader-api) endpoints return swap quotes and, on request, an assembled Solana transaction. Alchemy currently routes Trader API requests through Metis. + +{/* cu:auto product="solana-trader" */} +| Method | CU | Throughput CU | +| --------------------------- | --- | ------------- | +| build | 100 | 100 | +| order | 100 | 100 | +| quote-multiple-output-mints | 100 | 100 | +{/* cu:auto end */} + # Solana: Jito Bundles and Transactions [Jito bundles](/docs/chains/solana/solana-jito-bundles-and-transactions) are groups of up to 5 signed transactions that execute sequentially and atomically in a single slot on Solana Mainnet. A tip to one of the Jito tip accounts is required for inclusion. These methods are available on paid Alchemy plans only. diff --git a/content/api-reference/solana/solana-api-overview.mdx b/content/api-reference/solana/solana-api-overview.mdx index 76b6c1675..4b650ddda 100644 --- a/content/api-reference/solana/solana-api-overview.mdx +++ b/content/api-reference/solana/solana-api-overview.mdx @@ -48,3 +48,4 @@ The following Alchemy APIs are also supported on Solana: * [Bundler API](/docs/wallets/transactions/low-level-infra/bundler/overview) * [Gas Manager API](/docs/wallets/api-reference/gas-manager-admin-api/gas-abstraction-api-endpoints/alchemy-request-gas-and-paymaster-and-data) +* [Solana Trader API](/docs/chains/solana/solana-trader-api) — REST endpoints for pricing and building Solana token swaps. diff --git a/content/api-reference/solana/solana-trader-api-overview.mdx b/content/api-reference/solana/solana-trader-api-overview.mdx new file mode 100644 index 000000000..70f8001a8 --- /dev/null +++ b/content/api-reference/solana/solana-trader-api-overview.mdx @@ -0,0 +1,47 @@ +--- +title: Solana Trader API +description: Alchemy's REST endpoints for pricing and building Solana token swaps. +subtitle: Alchemy's REST endpoints for pricing and building Solana token swaps. +--- + +## Background + +The Solana Trader API returns swap quotes and, on request, an assembled +transaction that a taker can sign and broadcast. Use it to price a swap ahead +of time, present a route to a user, or hand a signable transaction to a +wallet. Requests use the same Alchemy API key as your other Solana calls. + +Alchemy routes Trader API requests through [Metis](https://station.jup.ag/blog/jupiter-swap-v2-metis), the routing engine that powers Jupiter's Swap V2 `/order` endpoint. If you have already integrated Jupiter's contract, the response shape here will feel familiar. Two differences worth calling out: + +* Alchemy carries auth in the URL path (see [Endpoint](#endpoint)), not in an `x-api-key` header. +* `/quote-multiple-output-mints` is an Alchemy-specific endpoint that returns quotes for one input mint against up to 32 candidate output mints in a single request. + +The API exposes three endpoints: + +* `GET /order` returns a swap quote. Pass a `taker` to also receive an unsigned base64 transaction; omit `taker` for a quote-only response. +* `GET /build` returns raw swap instructions for composing into your own transaction (multi-leg flows, program deposits, cleanup steps). +* `POST /quote-multiple-output-mints` returns quotes for a single input against up to 32 output mints in one call. + +## Endpoint + +Solana Trader API is available on **Solana Mainnet** through the standard Alchemy Solana endpoint. Devnet is not supported. + +```text +https://solana-mainnet.g.alchemy.com/v2/{apiKey} +``` + +Use your Solana Mainnet API key from the [Alchemy Dashboard](https://dashboard.alchemy.com/apps). The `docs-demo` key powers the Try It widget on the method pages below. + +## Methods + +| Method | Function | CU cost | Throughput CUs (how many CUs this will count for towards your CUs per second capacity) | +| --- | --- | --- | --- | +| [GET /order](/docs/chains/solana/solana-trader-api/solana-trader-api/get-swap-order) | Get a swap quote. Include a `taker` to also receive an unsigned base64 transaction; omit `taker` for quote fields only. | 100 | 100 | +| [GET /build](/docs/chains/solana/solana-trader-api/solana-trader-api/build-swap-instructions) | Return raw swap instructions for composing into your own transaction. | 100 | 100 | +| [POST /quote-multiple-output-mints](/docs/chains/solana/solana-trader-api/solana-trader-api/quote-multiple-output-mints) | Quote a single input mint against up to 32 candidate output mints in one call. | 100 | 100 | + +## Related + +* [`sendTransaction`](/docs/chains/solana/solana-api-endpoints/send-transaction) — submit the signed transaction returned by `/order` to the cluster. +* [Solana Jito Bundles and Transactions](/docs/chains/solana/solana-jito-bundles-and-transactions) — pair a signed swap with a Jito tip for atomic, low-latency inclusion. +* [Solana API Overview](/docs/solana/solana-api-overview) — the full Solana JSON-RPC surface. diff --git a/content/docs.yml b/content/docs.yml index 04a0e577c..41f71336a 100644 --- a/content/docs.yml +++ b/content/docs.yml @@ -365,6 +365,13 @@ navigation: - api: Solana Photon API api-name: solana-photon flattened: true + - section: Solana Trader API + path: >- + api-reference/solana/solana-trader-api-overview.mdx + contents: + - api: Solana Trader API + api-name: solana-trader + flattened: true - section: Solana Jito Bundles and Transactions path: >- api-reference/solana/solana-jito-bundles-overview.mdx diff --git a/src/openapi/solana-trader/solana-trader.yaml b/src/openapi/solana-trader/solana-trader.yaml new file mode 100644 index 000000000..679a12856 --- /dev/null +++ b/src/openapi/solana-trader/solana-trader.yaml @@ -0,0 +1,584 @@ +# yaml-language-server: $schema=https://spec.openapis.org/oas/3.1/schema/2022-10-07 + +openapi: 3.1.0 +info: + title: 💱 Solana Trader API + description: > + Alchemy's Solana Trader API returns swap quotes and, on request, an assembled + signable transaction for routing token swaps on Solana. Requests are + authenticated with your Alchemy API key in the URL path, the same key that + powers your other Solana RPC calls. Alchemy currently routes Trader API + requests through Metis. + version: "1.0" +servers: + - url: https://solana-mainnet.g.alchemy.com/v2 + description: Solana Mainnet +paths: + "/{apiKey}/order": + get: + summary: Get Order + description: > + Returns a swap quote for `inputMint` → `outputMint`. When `taker` is + supplied, the response also includes an unsigned, base64-encoded Solana + transaction the taker can sign and broadcast. When `taker` is omitted, + the response contains the quote only and `transaction` is `null`. + tags: ["Solana Trader API Endpoints"] + x-compute-units: 100 + x-rate-limit-cus: 100 + operationId: get-swap-order + parameters: + - $ref: "#/components/parameters/apiKey" + - $ref: "#/components/parameters/InputMint" + - $ref: "#/components/parameters/OutputMint" + - $ref: "#/components/parameters/Amount" + - name: taker + in: query + required: false + description: > + Public key of the wallet that will sign the transaction. When + omitted, the response returns a quote and `transaction` is `null`. + schema: + type: string + example: GkwFnmMDvn3HGMpJpWBg8tgJxr3NxNvg3AXxvXVPbRGJ + - name: receiver + in: query + required: false + description: > + Public key of the wallet that will receive the output tokens. Must + differ from `taker`. Expects a wallet address, not a token account. + For non-SOL output, tokens are sent to the receiver's associated + token account (ATA); a create-ATA instruction is added when the ATA + does not exist. + schema: + type: string + - name: swapMode + in: query + required: false + description: Swap mode. Currently only `ExactIn` is supported. + schema: + type: string + enum: [ExactIn] + default: ExactIn + - name: slippageBps + in: query + required: false + description: > + Slippage tolerance in basis points (0-10000). Alchemy picks a value + automatically when omitted. + schema: + type: integer + minimum: 0 + maximum: 10000 + example: 50 + - name: priorityFeeLamports + in: query + required: false + description: > + Priority fee in lamports. Overrides the automatic priority fee + Alchemy would otherwise pick. + schema: + type: integer + - name: jitoTipLamports + in: query + required: false + description: Jito MEV tip in lamports for faster block inclusion. + schema: + type: integer + - name: broadcastFeeType + in: query + required: false + description: > + Fee cap strategy. `maxCap` treats the supplied fee as a maximum; + `exactFee` sends the exact amount. Ignored when neither + `priorityFeeLamports` nor `jitoTipLamports` is set. + schema: + type: string + enum: [maxCap, exactFee] + - name: excludeDexes + in: query + required: false + description: > + Comma-separated list of DEX labels to exclude from routing. Labels + are case-sensitive (e.g. `Raydium,Orca+V2,Meteora+DLMM`). + schema: + type: string + responses: + "200": + description: Quote with optional assembled transaction. + content: + application/json: + schema: + $ref: "#/components/schemas/OrderResponse" + "400": + description: Malformed request or invalid parameters. + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "401": + description: Missing or invalid API key. + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "429": + description: Rate limit exceeded. + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + + "/{apiKey}/build": + get: + summary: Build Swap Instructions + description: > + Returns raw Solana swap instructions rather than a pre-built transaction. + Use `/build` when you need to compose the swap into a larger transaction + of your own (for example a program deposit before the swap or a + cleanup step after it). If you just need a signable transaction, use + `/order` with a `taker`. + tags: ["Solana Trader API Endpoints"] + x-compute-units: 100 + x-rate-limit-cus: 100 + operationId: build-swap-instructions + parameters: + - $ref: "#/components/parameters/apiKey" + - $ref: "#/components/parameters/InputMint" + - $ref: "#/components/parameters/OutputMint" + - $ref: "#/components/parameters/Amount" + - name: taker + in: query + required: true + description: > + Public key of the wallet that will sign the swap instructions. + Required for `/build` since the instructions must reference concrete + source and destination accounts. + schema: + type: string + example: GkwFnmMDvn3HGMpJpWBg8tgJxr3NxNvg3AXxvXVPbRGJ + - name: receiver + in: query + required: false + description: Public key of the wallet that will receive the output tokens. + schema: + type: string + - name: swapMode + in: query + required: false + description: Swap mode. Currently only `ExactIn` is supported. + schema: + type: string + enum: [ExactIn] + default: ExactIn + - name: slippageBps + in: query + required: false + description: > + Slippage tolerance in basis points (0-10000). Alchemy picks a value + automatically when omitted. + schema: + type: integer + minimum: 0 + maximum: 10000 + example: 50 + - name: excludeDexes + in: query + required: false + description: Comma-separated list of DEX labels to exclude from routing. + schema: + type: string + responses: + "200": + description: Raw swap instructions. + content: + application/json: + schema: + $ref: "#/components/schemas/BuildResponse" + "400": + description: Malformed request or invalid parameters. + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "401": + description: Missing or invalid API key. + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "429": + description: Rate limit exceeded. + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + + "/{apiKey}/quote-multiple-output-mints": + post: + summary: Quote Multiple Output Mints + description: > + Returns quotes for a single input mint against up to 32 candidate output + mints in one call. Useful for pricing a basket or comparing routes + across candidate outputs without issuing N separate requests. Each + entry in `quotes` follows the same shape as `/order` without a `taker`, + so responses carry the quote fields only and `transaction` is `null`. + tags: ["Solana Trader API Endpoints"] + x-compute-units: 100 + x-rate-limit-cus: 100 + operationId: quote-multiple-output-mints + parameters: + - $ref: "#/components/parameters/apiKey" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/MultiQuoteRequest" + responses: + "200": + description: Array of quotes, one per requested output mint. + content: + application/json: + schema: + $ref: "#/components/schemas/MultiQuoteResponse" + "400": + description: > + Malformed request or invalid parameters. Common cause is submitting + more than 32 output mints in `outputMints`. + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "401": + description: Missing or invalid API key. + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "429": + description: Rate limit exceeded. + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + +components: + securitySchemes: + apiKey: + type: apiKey + name: Authorization + in: header + description: > + Trader API requests carry the API key in the URL path, not in a header. + This scheme is defined to satisfy tooling and is unused by the + endpoints. + x-default: Bearer API_KEY + parameters: + apiKey: + name: apiKey + in: path + required: true + schema: + type: string + default: docs-demo + description: For higher throughput, [create your own API key](https://dashboard.alchemy.com/signup). + InputMint: + name: inputMint + in: query + required: true + description: Mint address of the input token. + schema: + type: string + default: So11111111111111111111111111111111111111112 + example: So11111111111111111111111111111111111111112 + OutputMint: + name: outputMint + in: query + required: true + description: Mint address of the output token. + schema: + type: string + default: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + example: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + Amount: + name: amount + in: query + required: true + description: > + Amount to swap in the smallest unit of the input token (lamports for + native SOL, base units for SPL tokens). + schema: + type: string + default: "1000000000" + example: "1000000000" + schemas: + OrderResponse: + type: object + description: Quote fields, plus an assembled transaction when a taker was supplied. + properties: + inputMint: + type: string + description: Mint of the input token, echoed back. + outputMint: + type: string + description: Mint of the output token, echoed back. + inAmount: + type: string + description: Input amount used for the quote, in base units of the input mint. + outAmount: + type: string + description: Estimated output amount before slippage, in base units of the output mint. + otherAmountThreshold: + type: string + description: Minimum output amount after slippage is applied. + swapMode: + type: string + description: Swap mode used to build the quote. + enum: [ExactIn] + slippageBps: + type: integer + description: Slippage tolerance in basis points. + priceImpact: + type: number + description: > + Price impact of the swap, in percentage points (for example, `-0.1` + means -0.1%). Divide by 100 to convert to a decimal fraction. + routePlan: + type: array + description: Ordered list of route steps that make up the swap. + items: + $ref: "#/components/schemas/RoutePlanStep" + router: + type: string + description: > + Router that produced the quote. Alchemy currently serves quotes + through Metis only. + enum: [metis] + transaction: + type: ["string", "null"] + description: > + Base64-encoded, unsigned Solana transaction. `null` when `taker` + was not supplied. Empty string when `taker` was supplied but the + router could not build a transaction — inspect `errorCode` and + `errorMessage` in that case. + lastValidBlockHeight: + type: string + description: Block height beyond which the assembled transaction is no longer valid. + signatureFeeLamports: + type: integer + description: Estimated signature fee in lamports. + prioritizationFeeLamports: + type: integer + description: Estimated priority fee plus any Jito tip, in lamports. + rentFeeLamports: + type: integer + description: > + Estimated rent fee in lamports (for example, to open the output + token account when it does not already exist). + requestId: + type: string + description: Unique identifier for the request. Include when reporting issues. + taker: + type: ["string", "null"] + description: Taker echoed back from the request. `null` when not supplied. + errorCode: + type: integer + description: > + Present only when `taker` was supplied and `transaction` is the + empty string. Match on `errorCode` to identify the failure: + + * `1` — insufficient funds + * `2` — insufficient SOL for gas + * `3` — swap below minimum for gasless + errorMessage: + type: string + description: > + Human-readable error description. Present when `errorCode` is set. + Match on `errorCode` rather than parsing this string. + required: + - inputMint + - outputMint + - inAmount + - outAmount + - swapMode + - slippageBps + - routePlan + - router + + BuildResponse: + type: object + description: Raw Solana swap instructions. + properties: + setupInstructions: + type: array + description: > + Instructions that must run before the swap (for example, create an + associated token account or wrap SOL). + items: + $ref: "#/components/schemas/Instruction" + swapInstruction: + $ref: "#/components/schemas/Instruction" + cleanupInstruction: + description: > + Optional instruction that runs after the swap (for example, close a + temporary wrapped-SOL account and reclaim rent). `null` when no + cleanup is required. + oneOf: + - $ref: "#/components/schemas/Instruction" + - type: "null" + addressLookupTableAddresses: + type: array + description: Address lookup table accounts the swap references. + items: + type: string + computeUnitLimit: + type: integer + description: Recommended compute unit limit for the transaction. + prioritizationFeeLamports: + type: integer + description: Recommended prioritization fee in lamports. + requestId: + type: string + description: Unique identifier for the request. + required: + - swapInstruction + + Instruction: + type: object + description: A Solana instruction in decomposed form. + properties: + programId: + type: string + description: Program ID that owns the instruction. + accounts: + type: array + items: + $ref: "#/components/schemas/AccountMeta" + data: + type: string + description: Base64-encoded instruction data. + required: + - programId + - accounts + - data + + AccountMeta: + type: object + properties: + pubkey: + type: string + isSigner: + type: boolean + isWritable: + type: boolean + required: + - pubkey + - isSigner + - isWritable + + RoutePlanStep: + type: object + properties: + swapInfo: + $ref: "#/components/schemas/SwapInfo" + percent: + type: number + description: Percentage of the total swap routed through this step (0-100). + required: + - swapInfo + - percent + + SwapInfo: + type: object + properties: + ammKey: + type: string + description: On-chain address of the AMM pool used for this step. + label: + type: string + description: Human-readable DEX label (for example, `Orca V2`, `Raydium CLMM`). + inputMint: + type: string + outputMint: + type: string + inAmount: + type: string + outAmount: + type: string + required: + - ammKey + - label + - inputMint + - outputMint + - inAmount + - outAmount + + MultiQuoteRequest: + type: object + properties: + inputMint: + type: string + description: Mint address of the input token. + example: So11111111111111111111111111111111111111112 + default: So11111111111111111111111111111111111111112 + amount: + type: string + description: Amount to swap, in base units of the input mint. + example: "1000000000" + default: "1000000000" + outputMints: + type: array + description: > + Mint addresses of the candidate output tokens. Up to 32 entries per + request. + minItems: 1 + maxItems: 32 + items: + type: string + example: + - EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + - Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB + swapMode: + type: string + enum: [ExactIn] + default: ExactIn + slippageBps: + type: integer + minimum: 0 + maximum: 10000 + description: Slippage tolerance in basis points applied to each quote. + required: + - inputMint + - amount + - outputMints + + MultiQuoteResponse: + type: object + properties: + quotes: + type: array + description: > + One quote per requested output mint, in the same order as + `outputMints` in the request. + items: + $ref: "#/components/schemas/OrderResponse" + requestId: + type: string + description: Unique identifier for the request. + required: + - quotes + + ErrorResponse: + type: object + properties: + error: + type: string + description: Human-readable error description. + errorCode: + type: integer + description: Machine-readable error code, when available. + requestId: + type: string + description: Unique identifier for the request. + required: + - error From 337c818f39055d2256a6ade4e3469b8610112887 Mon Sep 17 00:00:00 2001 From: alchemy-bot <80712764+alchemy-bot@users.noreply.github.com> Date: Tue, 15 Sep 2026 12:09:06 +0000 Subject: [PATCH 2/4] [docs-agent] Flatten Solana Trader API sidebar (drop operation tags) Vlad flagged that the sidebar was rendering as Solana Trader API > Solana Trader API Endpoints > , one level deeper than Solana Photon API. The extra middle level was the OpenAPI operation tag ('Solana Trader API Endpoints'): Fern groups OpenAPI operations by tag under the api entry even with flattened: true, whereas Solana Photon's OpenRPC methods carry no tags and render flat. Fix matches the Portfolio spec pattern (src/openapi/portfolio/portfolio.yaml uses no tags on its operations and renders flat under a single api heading in docs.yml). Drops tags from /order, /build, and /quote-multiple-output-mints so all three operations render directly under the Solana Trader API section. Refs DOCS-227 --- src/openapi/solana-trader/solana-trader.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/openapi/solana-trader/solana-trader.yaml b/src/openapi/solana-trader/solana-trader.yaml index 679a12856..624f99b06 100644 --- a/src/openapi/solana-trader/solana-trader.yaml +++ b/src/openapi/solana-trader/solana-trader.yaml @@ -22,7 +22,6 @@ paths: supplied, the response also includes an unsigned, base64-encoded Solana transaction the taker can sign and broadcast. When `taker` is omitted, the response contains the quote only and `transaction` is `null`. - tags: ["Solana Trader API Endpoints"] x-compute-units: 100 x-rate-limit-cus: 100 operationId: get-swap-order @@ -137,7 +136,6 @@ paths: of your own (for example a program deposit before the swap or a cleanup step after it). If you just need a signable transaction, use `/order` with a `taker`. - tags: ["Solana Trader API Endpoints"] x-compute-units: 100 x-rate-limit-cus: 100 operationId: build-swap-instructions @@ -222,7 +220,6 @@ paths: across candidate outputs without issuing N separate requests. Each entry in `quotes` follows the same shape as `/order` without a `taker`, so responses carry the quote fields only and `transaction` is `null`. - tags: ["Solana Trader API Endpoints"] x-compute-units: 100 x-rate-limit-cus: 100 operationId: quote-multiple-output-mints From fab6e2502e6f2a7fe3588d561d3658a20324bec0 Mon Sep 17 00:00:00 2001 From: alchemy-bot <80712764+alchemy-bot@users.noreply.github.com> Date: Tue, 15 Sep 2026 12:40:25 +0000 Subject: [PATCH 3/4] [docs-agent] Solana Trader API spec review pass (vlad's nits) Comprehensive rewrite of src/openapi/solana-trader/solana-trader.yaml against Vlad's spec-review pass. /order: * swapMode enum extended with ExactOut. otherAmountThreshold documented as max input on ExactOut, min output on ExactIn. * Response fields promoted to required (always present): mode, otherAmountThreshold, priceImpact, priceImpactPct, inUsdValue, outUsdValue, swapUsdValue, swapType, gasless, router, routePlan, transaction, taker, signatureFeeLamports, prioritizationFeeLamports, rentFeeLamports, signatureFeePayer, prioritizationFeePayer, rentFeePayer. transaction/taker/fee-payer fields nullable via type: [string, null]. * lastValidBlockHeight kept optional (omitted, not null, when there is no usable transaction). * Router-side requestId dropped (not emitted by this service; out of scope with /execute per Metis's README). * errorCode 3 dropped (never emitted, no gasless path). errorCode 1 and 2 retained. Added error field alongside errorCode/errorMessage for 200 rejections. * routePlan[] steps gained bps (0-10000) and optional usdValue. percent typed as integer 0-100. * Error responses (400, 401, 429) removed per Vlad's ask (200 only for now). * Three named examples: quoteOnly, withTransaction, pricedButUnexecutable. /build: * Request params overhauled. Dropped receiver and swapMode (silently ignored by Metis). slippageBps clarified: Metis default 50 when omitted, string rtse accepted alongside 0-10000 integer. * Added payer, dexes (mutually exclusive with excludeDexes), platformFeeBps (0-10000 with feeAccount required when positive), feeAccount, maxAccounts (1-64), wrapAndUnwrapSol, destinationTokenAccount / nativeDestinationAccount (mutually exclusive), blockhashSlotsToExpiry (1-300, with 256-300 as 501 note), tipAmount (> 0), computeUnitPricePercentile (medium | high | veryHigh only), mode (fast only), forJitoBundle. * Response schema rewritten. Dropped addressLookupTableAddresses, computeUnitLimit, prioritizationFeeLamports, requestId. * Added quote fields (inputMint, outputMint, inAmount, outAmount, otherAmountThreshold, swapMode ExactIn-only, slippageBps, priceImpactPct, routePlan), computeBudgetInstructions, otherInstructions, tipInstruction, addressesByLookupTableAddress (map keyed by lookup-table address, null when no tables in use), blockhashWithMetadata with a snake_case fetchedAt object (secs_since_epoch, nanos_since_epoch) and 32-byte integer array blockhash. * setupInstructions kept required (always present, may be empty). * Errors documented: 400 with plain {error: string} body, 501 for numeric computeUnitPricePercentile and blockhashSlotsToExpiry 256-300, 502 for Metis / priority-fee / lookup-table / blockhash / tip-instruction upstream failures. 401 and 429 omitted (gateway-only). * Single realistic 200 example. /quote-multiple-output-mints: * Response envelope rewritten. quotes changed from array to object keyed by output mint (in request order), each value only { inAmount, outAmount }. Shared contextSlot at the top level (omitted when no quote carried one). requestId removed. * Request body: dropped slippageBps (silently ignored server-side). Kept inputMint, outputMints (1-32 unique pubkeys, none equal to inputMint), amount (JSON string; number returns 400), swapMode (ExactIn or ExactOut, ExactOut = desired output per mint independently). * 400 documented with common causes (over 32 mints, amount as number, duplicate mint, mint equal to input). * Introduced dedicated MultiQuoteEntry component instead of reusing OrderResponse. Shared: * ErrorResponse simplified to { error: string } only. * Amount parameter description updated for ExactOut semantics. * redocly source lint clean (2 baseline warnings: info-license and operation-4xx-response on /order, both intentional). Refs DOCS-227 --- src/openapi/solana-trader/solana-trader.yaml | 810 +++++++++++++++---- 1 file changed, 671 insertions(+), 139 deletions(-) diff --git a/src/openapi/solana-trader/solana-trader.yaml b/src/openapi/solana-trader/solana-trader.yaml index 624f99b06..06ddcbe26 100644 --- a/src/openapi/solana-trader/solana-trader.yaml +++ b/src/openapi/solana-trader/solana-trader.yaml @@ -21,7 +21,7 @@ paths: Returns a swap quote for `inputMint` → `outputMint`. When `taker` is supplied, the response also includes an unsigned, base64-encoded Solana transaction the taker can sign and broadcast. When `taker` is omitted, - the response contains the quote only and `transaction` is `null`. + the response contains the quote and `transaction` is `null`. x-compute-units: 100 x-rate-limit-cus: 100 operationId: get-swap-order @@ -35,7 +35,8 @@ paths: required: false description: > Public key of the wallet that will sign the transaction. When - omitted, the response returns a quote and `transaction` is `null`. + omitted, the response returns a quote only and `transaction` is + `null`. schema: type: string example: GkwFnmMDvn3HGMpJpWBg8tgJxr3NxNvg3AXxvXVPbRGJ @@ -53,17 +54,21 @@ paths: - name: swapMode in: query required: false - description: Swap mode. Currently only `ExactIn` is supported. + description: > + Swap mode. `ExactIn` treats `amount` as the input amount and + slippage is applied on the output side; `ExactOut` treats `amount` + as the desired output amount and slippage is applied on the input + side. schema: type: string - enum: [ExactIn] + enum: [ExactIn, ExactOut] default: ExactIn - name: slippageBps in: query required: false description: > - Slippage tolerance in basis points (0-10000). Alchemy picks a value - automatically when omitted. + Slippage tolerance in basis points (0-10000). Metis defaults to 50 + when omitted. schema: type: integer minimum: 0 @@ -73,8 +78,8 @@ paths: in: query required: false description: > - Priority fee in lamports. Overrides the automatic priority fee - Alchemy would otherwise pick. + Priority fee in lamports. Overrides the automatic value Alchemy + would otherwise pick. schema: type: integer - name: jitoTipLamports @@ -98,44 +103,145 @@ paths: required: false description: > Comma-separated list of DEX labels to exclude from routing. Labels - are case-sensitive (e.g. `Raydium,Orca+V2,Meteora+DLMM`). + are case-sensitive (for example, `Raydium,Orca+V2,Meteora+DLMM`). schema: type: string responses: "200": - description: Quote with optional assembled transaction. + description: Quote, plus an assembled transaction when a `taker` was supplied. content: application/json: schema: $ref: "#/components/schemas/OrderResponse" - "400": - description: Malformed request or invalid parameters. - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "401": - description: Missing or invalid API key. - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "429": - description: Rate limit exceeded. - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" + examples: + quoteOnly: + summary: Quote-only (no taker) + value: + mode: manual + inputMint: So11111111111111111111111111111111111111112 + outputMint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + inAmount: "1000000000" + outAmount: "234506710" + otherAmountThreshold: "233333336" + swapMode: ExactIn + slippageBps: 50 + priceImpact: -0.05 + priceImpactPct: "-0.0005" + inUsdValue: 234.5 + outUsdValue: 234.2 + swapUsdValue: 234.3 + swapType: aggregator + gasless: false + router: metis + routePlan: + - swapInfo: + ammKey: 5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1 + label: Orca V2 + inputMint: So11111111111111111111111111111111111111112 + outputMint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + inAmount: "1000000000" + outAmount: "234506710" + percent: 100 + bps: 10000 + usdValue: 234.3 + transaction: null + taker: null + signatureFeeLamports: 0 + prioritizationFeeLamports: 0 + rentFeeLamports: 0 + signatureFeePayer: null + prioritizationFeePayer: null + rentFeePayer: null + withTransaction: + summary: Quote plus assembled transaction (taker supplied) + value: + mode: manual + inputMint: So11111111111111111111111111111111111111112 + outputMint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + inAmount: "1000000000" + outAmount: "234506710" + otherAmountThreshold: "233333336" + swapMode: ExactIn + slippageBps: 50 + priceImpact: -0.05 + priceImpactPct: "-0.0005" + inUsdValue: 234.5 + outUsdValue: 234.2 + swapUsdValue: 234.3 + swapType: aggregator + gasless: false + router: metis + routePlan: + - swapInfo: + ammKey: 5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1 + label: Orca V2 + inputMint: So11111111111111111111111111111111111111112 + outputMint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + inAmount: "1000000000" + outAmount: "234506710" + percent: 100 + bps: 10000 + usdValue: 234.3 + transaction: AQAAAA...base64-encoded-unsigned-transaction... + taker: GkwFnmMDvn3HGMpJpWBg8tgJxr3NxNvg3AXxvXVPbRGJ + lastValidBlockHeight: "300000000" + signatureFeeLamports: 5000 + prioritizationFeeLamports: 500000 + rentFeeLamports: 2039280 + signatureFeePayer: GkwFnmMDvn3HGMpJpWBg8tgJxr3NxNvg3AXxvXVPbRGJ + prioritizationFeePayer: GkwFnmMDvn3HGMpJpWBg8tgJxr3NxNvg3AXxvXVPbRGJ + rentFeePayer: GkwFnmMDvn3HGMpJpWBg8tgJxr3NxNvg3AXxvXVPbRGJ + pricedButUnexecutable: + summary: 200 rejection (priced but transaction could not be built) + value: + mode: manual + inputMint: So11111111111111111111111111111111111111112 + outputMint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + inAmount: "1000000000" + outAmount: "234506710" + otherAmountThreshold: "233333336" + swapMode: ExactIn + slippageBps: 50 + priceImpact: -0.05 + priceImpactPct: "-0.0005" + inUsdValue: 234.5 + outUsdValue: 234.2 + swapUsdValue: 234.3 + swapType: aggregator + gasless: false + router: metis + routePlan: + - swapInfo: + ammKey: 5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1 + label: Orca V2 + inputMint: So11111111111111111111111111111111111111112 + outputMint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + inAmount: "1000000000" + outAmount: "234506710" + percent: 100 + bps: 10000 + usdValue: 234.3 + transaction: "" + taker: GkwFnmMDvn3HGMpJpWBg8tgJxr3NxNvg3AXxvXVPbRGJ + signatureFeeLamports: 0 + prioritizationFeeLamports: 0 + rentFeeLamports: 0 + signatureFeePayer: null + prioritizationFeePayer: null + rentFeePayer: null + errorCode: 1 + errorMessage: Insufficient funds + error: Insufficient funds "/{apiKey}/build": get: summary: Build Swap Instructions description: > - Returns raw Solana swap instructions rather than a pre-built transaction. - Use `/build` when you need to compose the swap into a larger transaction - of your own (for example a program deposit before the swap or a - cleanup step after it). If you just need a signable transaction, use - `/order` with a `taker`. + Returns raw Solana swap instructions rather than a pre-built + transaction. Use `/build` when you need to compose the swap into a + larger transaction of your own (for example, a program deposit before + the swap or a cleanup step after it). If you just need a signable + transaction, use `/order` with a `taker`. x-compute-units: 100 x-rate-limit-cus: 100 operationId: build-swap-instructions @@ -154,58 +260,261 @@ paths: schema: type: string example: GkwFnmMDvn3HGMpJpWBg8tgJxr3NxNvg3AXxvXVPbRGJ - - name: receiver + - name: payer in: query required: false - description: Public key of the wallet that will receive the output tokens. + description: > + Public key of the wallet that pays signature, priority, and rent + fees. Defaults to `taker` when omitted. schema: type: string - - name: swapMode + - name: slippageBps + in: query + required: false + description: > + Slippage tolerance in basis points (0-10000). Metis defaults to 50 + when omitted. The literal string `rtse` is accepted in place of an + integer to opt into Metis's real-time slippage estimator. + schema: + oneOf: + - type: integer + minimum: 0 + maximum: 10000 + - type: string + enum: [rtse] + example: 50 + - name: dexes in: query required: false - description: Swap mode. Currently only `ExactIn` is supported. + description: > + Comma-separated list of DEX labels to allow-list for routing + (labels are case-sensitive). Mutually exclusive with `excludeDexes`. schema: type: string - enum: [ExactIn] - default: ExactIn - - name: slippageBps + - name: excludeDexes in: query required: false description: > - Slippage tolerance in basis points (0-10000). Alchemy picks a value - automatically when omitted. + Comma-separated list of DEX labels to exclude from routing (labels + are case-sensitive). Mutually exclusive with `dexes`. + schema: + type: string + - name: platformFeeBps + in: query + required: false + description: > + Integrator fee in basis points (0-10000). When set to a positive + value, `feeAccount` is required. schema: type: integer minimum: 0 maximum: 10000 - example: 50 - - name: excludeDexes + - name: feeAccount + in: query + required: false + description: > + Token account that receives the integrator fee. Required when + `platformFeeBps` is positive. + schema: + type: string + - name: maxAccounts + in: query + required: false + description: > + Upper bound on the number of accounts the swap transaction can + reference (1-64). Lower values keep the transaction well within the + Solana account limit at the cost of narrower routing. + schema: + type: integer + minimum: 1 + maximum: 64 + - name: wrapAndUnwrapSol + in: query + required: false + description: > + When `true`, Metis inserts wrap-SOL and unwrap-SOL instructions + around the swap so native SOL can be used directly as input or + output. + schema: + type: boolean + - name: destinationTokenAccount + in: query + required: false + description: > + Explicit destination SPL token account for the output tokens. + Mutually exclusive with `nativeDestinationAccount`. + schema: + type: string + - name: nativeDestinationAccount + in: query + required: false + description: > + Explicit destination wallet for native SOL output. Mutually + exclusive with `destinationTokenAccount`. + schema: + type: string + - name: blockhashSlotsToExpiry + in: query + required: false + description: > + Number of slots the returned blockhash remains valid for (1-300). + Metis types this as `uint8`, so values in the 256-300 range return + `501` rather than `400`. + schema: + type: integer + minimum: 1 + maximum: 300 + - name: tipAmount in: query required: false - description: Comma-separated list of DEX labels to exclude from routing. + description: > + Jito tip amount in lamports (greater than 0). When set, Metis + surfaces a `tipInstruction` in the response for the caller to + include in the final transaction. + schema: + type: integer + minimum: 1 + - name: computeUnitPricePercentile + in: query + required: false + description: > + Priority-fee percentile to target. Only the string values `medium`, + `high`, and `veryHigh` are accepted. A numeric value returns `501`. + When omitted, Metis prices compute units itself. schema: type: string + enum: [medium, high, veryHigh] + - name: mode + in: query + required: false + description: > + Reserved for future routing modes. Only `fast` is currently valid; + any other value returns `400`. Accepting it does not change + routing. + schema: + type: string + enum: [fast] + - name: forJitoBundle + in: query + required: false + description: > + Set to `true` when you plan to submit the swap inside a Jito + bundle. Adjusts instruction ordering and priority-fee handling for + bundle inclusion. + schema: + type: boolean responses: "200": - description: Raw swap instructions. + description: Quote fields plus decomposed swap instructions. content: application/json: schema: $ref: "#/components/schemas/BuildResponse" + example: + inputMint: So11111111111111111111111111111111111111112 + outputMint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + inAmount: "1000000000" + outAmount: "234506710" + otherAmountThreshold: "233333336" + swapMode: ExactIn + slippageBps: 50 + priceImpactPct: "-0.0005" + routePlan: + - swapInfo: + ammKey: 5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1 + label: Orca V2 + inputMint: So11111111111111111111111111111111111111112 + outputMint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + inAmount: "1000000000" + outAmount: "234506710" + percent: 100 + bps: 10000 + usdValue: 234.3 + setupInstructions: [] + swapInstruction: + programId: JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4 + accounts: + - pubkey: GkwFnmMDvn3HGMpJpWBg8tgJxr3NxNvg3AXxvXVPbRGJ + isSigner: true + isWritable: true + data: AQAAAA... + cleanupInstruction: null + computeBudgetInstructions: + - programId: ComputeBudget111111111111111111111111111111 + accounts: [] + data: AgAAAA== + otherInstructions: [] + tipInstruction: null + addressesByLookupTableAddress: + AddrLookupTab1e1111111111111111111111111111: + - EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v + - So11111111111111111111111111111111111111112 + blockhashWithMetadata: + blockhash: + [ + 12, + 34, + 56, + 78, + 90, + 12, + 34, + 56, + 78, + 90, + 12, + 34, + 56, + 78, + 90, + 12, + 34, + 56, + 78, + 90, + 12, + 34, + 56, + 78, + 90, + 12, + 34, + 56, + 78, + 90, + 12, + 34, + ] + lastValidBlockHeight: "300000000" + fetchedAt: + secs_since_epoch: 1750000000 + nanos_since_epoch: 0 "400": - description: Malformed request or invalid parameters. + description: > + Malformed request or invalid parameters. Body is + `{"error":""}` only — no `errorCode`, no `requestId`. content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - "401": - description: Missing or invalid API key. + "501": + description: > + Parameter typed correctly but out of range. Currently emitted for: + + * `computeUnitPricePercentile` sent as a number instead of one of + `medium` / `high` / `veryHigh`. + * `blockhashSlotsToExpiry` in the 256-300 range (Metis types the + field as `uint8`). content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - "429": - description: Rate limit exceeded. + "502": + description: > + Upstream failure. Emitted for a Metis routing failure, a + priority-fee estimate failure, a lookup-table resolve failure, a + missing blockhash, or a `tipAmount` request that Metis could not + match to a tip instruction. content: application/json: schema: @@ -215,11 +524,12 @@ paths: post: summary: Quote Multiple Output Mints description: > - Returns quotes for a single input mint against up to 32 candidate output - mints in one call. Useful for pricing a basket or comparing routes - across candidate outputs without issuing N separate requests. Each - entry in `quotes` follows the same shape as `/order` without a `taker`, - so responses carry the quote fields only and `transaction` is `null`. + Returns quotes for a single input mint against up to 32 candidate + output mints in one call. Useful for pricing a basket or comparing + outputs without issuing N separate requests. Each quote in the + response carries only `inAmount` and `outAmount`; use `/order` for the + full quote surface (route plan, fees, transaction) on a single mint + pair. x-compute-units: 100 x-rate-limit-cus: 100 operationId: quote-multiple-output-mints @@ -233,27 +543,29 @@ paths: $ref: "#/components/schemas/MultiQuoteRequest" responses: "200": - description: Array of quotes, one per requested output mint. + description: > + An object keyed by output mint (in request order) with the priced + amounts for each, plus a shared `contextSlot`. content: application/json: schema: $ref: "#/components/schemas/MultiQuoteResponse" + example: + quotes: + EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v: + inAmount: "1000000000" + outAmount: "234506710" + Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB: + inAmount: "1000000000" + outAmount: "234481933" + contextSlot: 300000000 "400": description: > - Malformed request or invalid parameters. Common cause is submitting - more than 32 output mints in `outputMints`. - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "401": - description: Missing or invalid API key. - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "429": - description: Rate limit exceeded. + Malformed request body or invalid parameters. Body is + `{"error":""}` only. Common causes are submitting more + than 32 output mints, sending `amount` as a JSON number, an + `outputMints` entry equal to `inputMint`, or a duplicate mint in + `outputMints`. content: application/json: schema: @@ -303,7 +615,8 @@ components: required: true description: > Amount to swap in the smallest unit of the input token (lamports for - native SOL, base units for SPL tokens). + native SOL, base units for SPL tokens). On `ExactOut`, this is the + desired output amount instead. schema: type: string default: "1000000000" @@ -311,8 +624,11 @@ components: schemas: OrderResponse: type: object - description: Quote fields, plus an assembled transaction when a taker was supplied. + description: Quote fields plus an assembled transaction when a taker was supplied. properties: + mode: + type: string + description: Router mode used to price the quote. inputMint: type: string description: Mint of the input token, echoed back. @@ -324,14 +640,19 @@ components: description: Input amount used for the quote, in base units of the input mint. outAmount: type: string - description: Estimated output amount before slippage, in base units of the output mint. + description: > + Estimated output amount before slippage, in base units of the + output mint. otherAmountThreshold: type: string - description: Minimum output amount after slippage is applied. + description: > + Slippage threshold, in base units. On `ExactIn` this is the minimum + output amount after slippage; on `ExactOut` this is the maximum + input amount after slippage. Always present. swapMode: type: string description: Swap mode used to build the quote. - enum: [ExactIn] + enum: [ExactIn, ExactOut] slippageBps: type: integer description: Slippage tolerance in basis points. @@ -339,78 +660,185 @@ components: type: number description: > Price impact of the swap, in percentage points (for example, `-0.1` - means -0.1%). Divide by 100 to convert to a decimal fraction. - routePlan: - type: array - description: Ordered list of route steps that make up the swap. - items: - $ref: "#/components/schemas/RoutePlanStep" + means -0.1%). Always present. + priceImpactPct: + type: string + description: > + Price impact as a decimal fraction string. Divide `priceImpact` by + 100 to reconcile the two values. + inUsdValue: + type: number + description: USD value of the input amount at quote time. + outUsdValue: + type: number + description: USD value of the output amount at quote time. + swapUsdValue: + type: number + description: USD value of the swap at quote time. + swapType: + type: string + description: Router category that produced the quote (for example, `aggregator`). + gasless: + type: boolean + description: > + `true` when signature and priority fees are paid by a wallet other + than the taker. router: type: string description: > Router that produced the quote. Alchemy currently serves quotes through Metis only. enum: [metis] + routePlan: + type: array + description: Ordered list of route steps that make up the swap. + items: + $ref: "#/components/schemas/RoutePlanStep" transaction: type: ["string", "null"] description: > - Base64-encoded, unsigned Solana transaction. `null` when `taker` - was not supplied. Empty string when `taker` was supplied but the - router could not build a transaction — inspect `errorCode` and - `errorMessage` in that case. + Base64-encoded, unsigned Solana transaction. Always present. `null` + when `taker` was not supplied. Empty string when `taker` was + supplied but the router could not build a transaction — inspect + `errorCode`, `errorMessage`, and `error` in that case. + taker: + type: ["string", "null"] + description: > + Taker echoed back from the request. Always present. `null` when + `taker` was not supplied. lastValidBlockHeight: type: string - description: Block height beyond which the assembled transaction is no longer valid. + description: > + Block height beyond which the assembled transaction is no longer + valid. Omitted (not `null`) when the response does not carry a + usable transaction. signatureFeeLamports: type: integer - description: Estimated signature fee in lamports. + description: > + Estimated signature fee in lamports. Always present. `0` when + `taker` was not supplied or when the transaction was rejected. prioritizationFeeLamports: type: integer - description: Estimated priority fee plus any Jito tip, in lamports. + description: > + Estimated priority fee plus any Jito tip, in lamports. Always + present. `0` when `taker` was not supplied or when the transaction + was rejected. rentFeeLamports: type: integer description: > Estimated rent fee in lamports (for example, to open the output - token account when it does not already exist). - requestId: - type: string - description: Unique identifier for the request. Include when reporting issues. - taker: + token account when it does not already exist). Always present. `0` + when `taker` was not supplied or when the transaction was + rejected. + signatureFeePayer: type: ["string", "null"] - description: Taker echoed back from the request. `null` when not supplied. + description: > + Public key that pays the signature fee. `null` when `taker` was not + supplied or when the transaction was rejected. + prioritizationFeePayer: + type: ["string", "null"] + description: > + Public key that pays the priority fee and any Jito tip. `null` when + `taker` was not supplied or when the transaction was rejected. + rentFeePayer: + type: ["string", "null"] + description: > + Public key that pays the rent fee. `null` when `taker` was not + supplied or when the transaction was rejected. errorCode: type: integer description: > - Present only when `taker` was supplied and `transaction` is the - empty string. Match on `errorCode` to identify the failure: + Present only on a 200 rejection (`taker` was supplied but + `transaction` is the empty string). Match on `errorCode` to + identify the failure: * `1` — insufficient funds * `2` — insufficient SOL for gas - * `3` — swap below minimum for gasless errorMessage: type: string description: > - Human-readable error description. Present when `errorCode` is set. - Match on `errorCode` rather than parsing this string. + Human-readable error description. Present on a 200 rejection + alongside `errorCode`. Match on `errorCode` rather than parsing + this string. + error: + type: string + description: > + Duplicate of `errorMessage`, kept for compatibility. Present on a + 200 rejection alongside `errorCode`. required: + - mode - inputMint - outputMint - inAmount - outAmount + - otherAmountThreshold - swapMode - slippageBps - - routePlan + - priceImpact + - priceImpactPct + - inUsdValue + - outUsdValue + - swapUsdValue + - swapType + - gasless - router + - routePlan + - transaction + - taker + - signatureFeeLamports + - prioritizationFeeLamports + - rentFeeLamports + - signatureFeePayer + - prioritizationFeePayer + - rentFeePayer BuildResponse: type: object - description: Raw Solana swap instructions. + description: Quote fields plus decomposed swap instructions. properties: + inputMint: + type: string + description: Mint of the input token, echoed back. + outputMint: + type: string + description: Mint of the output token, echoed back. + inAmount: + type: string + description: Input amount used for the quote, in base units of the input mint. + outAmount: + type: string + description: > + Estimated output amount before slippage, in base units of the + output mint. + otherAmountThreshold: + type: string + description: > + Minimum output amount after slippage is applied, in base units of + the output mint. `/build` is `ExactIn` only, so this is always a + minimum output. + swapMode: + type: string + description: > + Swap mode used to build the instructions. `/build` supports + `ExactIn` only. + enum: [ExactIn] + slippageBps: + type: integer + description: Slippage tolerance in basis points applied to the quote. + priceImpactPct: + type: string + description: Price impact as a decimal fraction string. + routePlan: + type: array + description: Ordered list of route steps that make up the swap. + items: + $ref: "#/components/schemas/RoutePlanStep" setupInstructions: type: array description: > Instructions that must run before the swap (for example, create an - associated token account or wrap SOL). + associated token account or wrap SOL). Always present; may be + empty. items: $ref: "#/components/schemas/Instruction" swapInstruction: @@ -423,22 +851,100 @@ components: oneOf: - $ref: "#/components/schemas/Instruction" - type: "null" - addressLookupTableAddresses: + computeBudgetInstructions: type: array - description: Address lookup table accounts the swap references. + description: > + Compute-budget instructions returned by Metis (compute-unit limit, + compute-unit price). Always present; may be empty when Metis + declines to set a budget. items: - type: string - computeUnitLimit: - type: integer - description: Recommended compute unit limit for the transaction. - prioritizationFeeLamports: - type: integer - description: Recommended prioritization fee in lamports. - requestId: - type: string - description: Unique identifier for the request. + $ref: "#/components/schemas/Instruction" + otherInstructions: + type: array + description: > + Additional instructions Metis wants included in the final + transaction (for example, integrator fee transfers). Always + present; may be empty. + items: + $ref: "#/components/schemas/Instruction" + tipInstruction: + description: > + Jito tip instruction to include in the final transaction. Present + only when the request supplied `tipAmount`; otherwise `null`. + oneOf: + - $ref: "#/components/schemas/Instruction" + - type: "null" + addressesByLookupTableAddress: + type: ["object", "null"] + description: > + Address lookup table accounts referenced by the swap, keyed by + lookup-table address. Each value is the ordered list of accounts + resolved from that table. `null` when the route uses no lookup + tables. Never an empty object. + additionalProperties: + type: array + items: + type: string + blockhashWithMetadata: + $ref: "#/components/schemas/BlockhashWithMetadata" required: + - inputMint + - outputMint + - inAmount + - outAmount + - otherAmountThreshold + - swapMode + - slippageBps + - priceImpactPct + - routePlan + - setupInstructions - swapInstruction + - cleanupInstruction + - computeBudgetInstructions + - otherInstructions + - tipInstruction + - addressesByLookupTableAddress + - blockhashWithMetadata + + BlockhashWithMetadata: + type: object + description: > + Recent blockhash Metis fetched for the swap transaction, plus its + expiry and fetch timestamp. + properties: + blockhash: + type: array + description: > + Blockhash as a 32-byte little-endian array of unsigned integers, + NOT base58-encoded. + minItems: 32 + maxItems: 32 + items: + type: integer + minimum: 0 + maximum: 255 + lastValidBlockHeight: + type: string + description: Block height beyond which the blockhash is no longer valid. + fetchedAt: + type: object + description: > + Timestamp Metis fetched the blockhash. Keys are snake_case as + returned by the service. + properties: + secs_since_epoch: + type: integer + description: Seconds since Unix epoch. + nanos_since_epoch: + type: integer + description: Nanoseconds portion of the timestamp. + required: + - secs_since_epoch + - nanos_since_epoch + required: + - blockhash + - lastValidBlockHeight + - fetchedAt Instruction: type: object @@ -479,11 +985,22 @@ components: swapInfo: $ref: "#/components/schemas/SwapInfo" percent: - type: number + type: integer description: Percentage of the total swap routed through this step (0-100). + minimum: 0 + maximum: 100 + bps: + type: integer + description: Basis-points share of the total swap routed through this step (0-10000). + minimum: 0 + maximum: 10000 + usdValue: + type: number + description: Optional USD value of this step at quote time. required: - swapInfo - percent + - bps SwapInfo: type: object @@ -520,14 +1037,17 @@ components: default: So11111111111111111111111111111111111111112 amount: type: string - description: Amount to swap, in base units of the input mint. + description: > + Amount to price, in base units of the input mint (or the desired + output amount when `swapMode` is `ExactOut`). Must be a JSON + string; a JSON number returns `400`. example: "1000000000" default: "1000000000" outputMints: type: array description: > - Mint addresses of the candidate output tokens. Up to 32 entries per - request. + Mint addresses of the candidate output tokens (1-32). Entries must + be unique and none may equal `inputMint`. minItems: 1 maxItems: 32 items: @@ -537,13 +1057,11 @@ components: - Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB swapMode: type: string - enum: [ExactIn] + enum: [ExactIn, ExactOut] default: ExactIn - slippageBps: - type: integer - minimum: 0 - maximum: 10000 - description: Slippage tolerance in basis points applied to each quote. + description: > + Swap mode applied to every quote in the batch. On `ExactOut`, + `amount` is the desired output for each mint independently. required: - inputMint - amount @@ -551,31 +1069,45 @@ components: MultiQuoteResponse: type: object + description: > + Priced amounts for each requested output mint, plus a shared context + slot. The response deliberately omits route plans, fees, transactions, + and per-mint errors — use `/order` for the full quote surface on a + single mint pair. properties: quotes: - type: array + type: object description: > - One quote per requested output mint, in the same order as - `outputMints` in the request. - items: - $ref: "#/components/schemas/OrderResponse" - requestId: - type: string - description: Unique identifier for the request. + Object keyed by output mint (in request order). Each value carries + the priced amounts only. + additionalProperties: + $ref: "#/components/schemas/MultiQuoteEntry" + contextSlot: + type: integer + description: > + Oldest slot any quote in `quotes` reported. Omitted when none of + the quotes carried a slot. required: - quotes + MultiQuoteEntry: + type: object + properties: + inAmount: + type: string + description: Input amount in base units of the input mint. + outAmount: + type: string + description: Priced output amount in base units of the output mint. + required: + - inAmount + - outAmount + ErrorResponse: type: object properties: error: type: string description: Human-readable error description. - errorCode: - type: integer - description: Machine-readable error code, when available. - requestId: - type: string - description: Unique identifier for the request. required: - error From ac653fbf7c0768183ade207f97be79e4d5c00d4a Mon Sep 17 00:00:00 2001 From: alchemy-bot <80712764+alchemy-bot@users.noreply.github.com> Date: Tue, 15 Sep 2026 12:50:35 +0000 Subject: [PATCH 4/4] [docs-agent] Drop 4xx/5xx responses on /build and /quote-multiple-output-mints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Matches Vlad's earlier ask for /order — all three operations now document 200 only. Removes 400 + 501 + 502 from /build and 400 from /quote-multiple-output-mints. Also drops the now-unreferenced ErrorResponse component from the source (bundler would strip it via --remove-unused-components anyway, but keeping the source tidy). Refs DOCS-227 --- src/openapi/solana-trader/solana-trader.yaml | 50 -------------------- 1 file changed, 50 deletions(-) diff --git a/src/openapi/solana-trader/solana-trader.yaml b/src/openapi/solana-trader/solana-trader.yaml index 06ddcbe26..d8c8f487b 100644 --- a/src/openapi/solana-trader/solana-trader.yaml +++ b/src/openapi/solana-trader/solana-trader.yaml @@ -489,36 +489,6 @@ paths: fetchedAt: secs_since_epoch: 1750000000 nanos_since_epoch: 0 - "400": - description: > - Malformed request or invalid parameters. Body is - `{"error":""}` only — no `errorCode`, no `requestId`. - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "501": - description: > - Parameter typed correctly but out of range. Currently emitted for: - - * `computeUnitPricePercentile` sent as a number instead of one of - `medium` / `high` / `veryHigh`. - * `blockhashSlotsToExpiry` in the 256-300 range (Metis types the - field as `uint8`). - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "502": - description: > - Upstream failure. Emitted for a Metis routing failure, a - priority-fee estimate failure, a lookup-table resolve failure, a - missing blockhash, or a `tipAmount` request that Metis could not - match to a tip instruction. - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" "/{apiKey}/quote-multiple-output-mints": post: @@ -559,17 +529,6 @@ paths: inAmount: "1000000000" outAmount: "234481933" contextSlot: 300000000 - "400": - description: > - Malformed request body or invalid parameters. Body is - `{"error":""}` only. Common causes are submitting more - than 32 output mints, sending `amount` as a JSON number, an - `outputMints` entry equal to `inputMint`, or a duplicate mint in - `outputMints`. - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" components: securitySchemes: @@ -1102,12 +1061,3 @@ components: required: - inAmount - outAmount - - ErrorResponse: - type: object - properties: - error: - type: string - description: Human-readable error description. - required: - - error