Docs

API reference

Two live endpoints on Solana mainnet, free during the beta, no key. /api/explain says what happened in a transaction, what it cost and what to do next. /api/errors is the public error catalog.

  • Version 0.1.0 · beta
  • Base URL https://www.unstucksol.com/api
  • OpenAPI 3.1 openapi.yaml

Overview

JSON over HTTPS at https://www.unstucksol.com/api. Both endpoints read Solana mainnet live, need no key and no sign-in, and are free during the beta.

Price

Today
Free. Beta: calls are free; the x402 flow is the planned paid tier and is not enforced.
Planned
0.10 USDC per explain call over x402, in USDC on Solana, with no account. The catalog stays free. How it will work

Machine-readable: openapi.yaml · SKILL.md · llms.txt · MCP server card (planned)

Try it now

Paste this into a terminal. It asks about a real swap on mainnet that failed on its slippage limit.

Request
$ curl 'https://www.unstucksol.com/api/explain?sig=3cbDDFD5GrPVzJZCfP8ppSGiTFHd6RHQBbgkrgRpXLbu2fbSPdKdgjimJduvMhRP3N8yh6QznSmtSVbh3feUwV2R'

Response 200 (program logs trimmed)

{
  "signature": "3cbDDFD5GrPVzJZCfP8ppSGiTFHd6RHQBbgkrgRpXLbu2fbSPdKdgjimJduvMhRP3N8yh6QznSmtSVbh3feUwV2R",
  "status": "failed",
  "title": "Slippage limit exceeded",
  "program": "Jupiter v6",
  "via": null,
  "raw_error": "{\"InstructionError\":[5,{\"Custom\":6001}]}",
  "raw_message": "custom program error: 0x1771",
  "decoded": "SlippageToleranceExceeded (6001)",
  "plain": "The price moved more than your slippage limit allowed, so the swap was cancelled.",
  "cost": { "sol": 0.00002191, "note": "Network fee only (incl. 0.00001691 SOL priority fee). Nothing was swapped or sent." },
  "balance_changes": [
    { "asset": "SOL", "mint": null, "delta": -0.00002191, "delta_ui": "-0.00002191", "note": "network fee" },
    { "asset": "PUMP", "mint": "pumpCmXqMfrsAkQ5r49WcJnRayYRqmXz6ae8H7H9Dfn", "delta": 0, "delta_ui": "0", "note": "unchanged" },
    { "asset": "USDC", "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "delta": 0, "delta_ui": "0", "note": "unchanged" }
  ],
  "fix": { "action": "retry", "params": { "fresh_quote": true }, "safe": true },
  "handoff": false,
  "slot": 456949936,
  "block_time": 1792005100,
  "explorer": "https://solscan.io/tx/3cbDDFD5GrPVzJZCfP8ppSGiTFHd6RHQBbgkrgRpXLbu2fbSPdKdgjimJduvMhRP3N8yh6QznSmtSVbh3feUwV2R",
  "fee_payer": "4B8srvotmWddTZuMt4RrBQrnx1sQj2Z7FaXgLbWvpVdd",
  "programs": ["System Program", "Token Program", "Jupiter v6"],
  "error_logs": ["Program JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4 failed: custom program error: 0x1771"],
  "logs": ["…the last 12 program log lines…"],
  "audience": "user"
}

GET /explain

What happened in a transaction, what it cost and what to do next. Live, free during the beta.

Send a signature, or an explorer link that contains one, as ?sig=. POST /explain takes the same fields as JSON. Answers are cached for 5 minutes.

Request

  • sigstringRequired

    A mainnet transaction signature in base58 (87 or 88 characters), or an explorer link with /tx/<signature> in it. signature works as the parameter name too. Devnet and testnet links are refused with a 400.

  • audience"user" | "agent"Default "user"

    Who reads the answer. It is echoed back in the response; in the beta both values return the same fields.

POST /explain with content-type: application/json and a body like {"signature": "<signature>", "audience": "agent"}.

Responses

  • 200Explanation

    The answer. Fields below.

  • 404Explanation

    The signature isn’t on mainnet: an Explanation with status: "not_found", a plain answer and a fix to send it again.

  • 400{ error, usage }

    Missing or malformed signature, a wallet address instead of a signature, a devnet link, or an audience other than user or agent. error says which, in plain words.

  • 429{ error }

    Too many lookups from one address, or the Solana RPC is busy. Wait for Retry-After seconds.

  • 502 · 504{ error }

    The Solana RPC failed or took too long. Try again in a moment.

  • 405 · 500 · 503{ error }

    Wrong method (use GET or POST), an unexpected error, or the service isn’t available.

Response fields: Explanation

  • signaturestring

    The signature you asked about (taken out of the link if you sent one).

  • status"failed" | "succeeded" | "not_found"

    What happened to the transaction. succeeded answers say what it did, like a swap or a transfer.

  • titlestring

    A short name for what happened, e.g. Slippage limit exceeded or Swap on Jupiter v6.

  • program · viastring · string | null

    The program the answer is about, and the program that called it when the failure happened one level down.

  • raw_error · raw_messagestring | null

    The chain’s error object as JSON text, and the error as wallets print it, e.g. custom program error: 0x1771. null when nothing failed.

  • decodedstring | null

    Error name and code, decoded against the program that failed, e.g. SlippageToleranceExceeded (6001).

  • plainstring

    What happened, in plain words. Quote it to people as it is.

  • cost{ sol, note }

    SOL the transaction cost the fee payer (network fee, priority fee and tips), and what that covers.

  • balance_changesarray

    Up to 8 of the fee payer’s balance changes: asset, mint, delta (number), delta_ui (exact decimal text) and note. Negative means it left the wallet.

  • fix{ action, params, safe }

    A fix your code can apply: parameters, never a transaction.

    • action"retry" | "add_sol" | "use_token_account" | "none"

      What kind of fix it is.

    • paramsobject

      The exact settings. Possible keys: slippage_bps, fresh_quote, refresh_route, compute_unit_limit, fresh_blockhash, sol, mint.

    • safeboolean

      true for retries with a stated setting and for adding a little SOL to the same wallet. Apply a fix automatically only when this is true. What safe means

  • handoffboolean

    Reserved for topics a person should decide, like risk, refunds or account access. Always false in the beta.

  • slot · block_timenumber | null

    Where the transaction landed, and when (Unix seconds).

  • explorer · fee_payer · programsstring · string | null · string[]

    A Solscan link, the wallet that paid the fee, and the programs the transaction ran.

  • error_logs · logsstring[]

    Up to 3 log lines that mention the error, and the last 12 program log lines.

  • audience"user" | "agent"

    The audience you asked for.

Examples

curl

A GET with the signature. No key.

$ curl 'https://www.unstucksol.com/api/explain?sig=3cbDDFD5GrPVzJZCfP8ppSGiTFHd6RHQBbgkrgRpXLbu2fbSPdKdgjimJduvMhRP3N8yh6QznSmtSVbh3feUwV2R'

GET /errors

The public error catalog: the raw Solana error, decoded, in plain words, with the typical fix. Live and free, no key.

Query parameters

  • qstringOptional

    Only entries that contain this text, like 0x1771, rent or Pump.fun. Leave it out to get the whole catalog.

Response 200

An array of entries. The catalog is cached for an hour.

  • rawstring

    The error as the chain reports it, e.g. custom program error: 0x1771.

  • decodedstring

    Name and code, e.g. SlippageToleranceExceeded (6001).

  • plainstring

    The same situation in plain words.

  • typical_fixstring

    What usually fixes it.

  • program · categorystring

    Which program the code belongs to (codes mean different things in different programs), and the kind of problem, e.g. slippage.

Example
$ curl 'https://www.unstucksol.com/api/errors?q=0x1771'

Response (first of three entries)

[
  {
    "raw": "custom program error: 0x1771",
    "decoded": "SlippageToleranceExceeded (6001)",
    "plain": "The price moved more than your slippage limit allowed, so the swap was cancelled.",
    "typical_fix": "Retry with a fresh quote and a slightly higher slippage limit (at most double, up to 3%).",
    "program": "Jupiter v6",
    "category": "slippage"
  },
  …
]

Public error catalog

A sample of the entries GET /api/errors returns, word for word. The full catalog is one request away: /api/errors. Public error strings only, no signatures, wallets or messages from users.

9 sample entries

Raw Decoded Plain Typical fix
Slippage limit exceededcustom program error: 0x1771 SlippageToleranceExceeded (6001) · Jupiter v6

The price moved more than your slippage limit allowed, so the swap was cancelled.

Retry with a fresh quote and a slightly higher slippage limit (at most double, up to 3%).

retry · slippage_bps, fresh_quote
Blockhash expiredBlockhash not found TransactionError: BlockhashNotFound

Your transaction waited too long and expired. Nothing was sent — just try again.

Send it again with a fresh blockhash.

retry · fresh_blockhash
Not enough SOL for rentTransaction results in an account with insufficient funds for rent TransactionError: InsufficientFundsForRent

This needed a small refundable SOL deposit to open an account, and the wallet was short. Add a little SOL and retry.

Add about 0.003 SOL, then retry.

add_sol · sol
No SOL for feesAttempt to debit an account but found no record of a prior credit. TransactionError: AccountNotFound

This wallet has no SOL for the network fee yet. Every transaction needs a tiny amount of SOL.

Send a little SOL to the wallet first (0.01 SOL covers many fees).

add_sol · sol
Not enough tokenscustom program error: 0x1 InsufficientFunds (1) · Token Program

There weren’t enough tokens in the account for this amount, so nothing moved. Check the balance and try a smaller amount.

Check the token balance and send or swap a smaller amount.

none
Wrong token accountcustom program error: 0x2 InvalidMint (2) · Token Program

The tokens were pointed at a token account that doesn’t match this coin or this wallet, so nothing moved.

Use the wallet’s own associated token account for this mint.

use_token_account · mint
Compute limit exceededComputational budget exceeded InstructionError: ComputationalBudgetExceeded

The transaction ran out of compute before it finished, so nothing happened. Retrying with a higher compute limit usually works.

Retry with a higher compute unit limit.

retry · compute_unit_limit
Token account frozencustom program error: 0x11 AccountFrozen (17) · Token Program

This token account is frozen by the token’s issuer, so these tokens can’t move. Only the issuer can unfreeze it.

Nothing to retry. Only the token’s freeze authority can unfreeze the account.

none
Bonding curve completecustom program error: 0x1775 BondingCurveComplete (6005) · Pump.fun

This coin has finished its Pump.fun bonding curve and now trades in a regular pool, so the curve can’t fill this trade. Trade it on PumpSwap or through Jupiter.

Trade the coin on its pool (PumpSwap) or through Jupiter.

none

Codes are per program: 0x1771 is 6001, and 6001 means different things in different programs. Unstuck decodes the code against the program that failed.

Limits

Price
Free during the beta. No keys, no free-tier counters.
Rate limit
Roughly 30 explain lookups a minute per IP address. Over that, 429 Too Many Requests with Retry-After.
Caching
Answers are cached for 5 minutes, the catalog for an hour.
Network
Solana mainnet only.

What is logged: security model.

Planned

Not live yet. This is the intended shape, so you can plan for it.

Paid tier: x402

Beta: calls are free; the x402 flow is the planned paid tier and is not enforced.

x402 puts the price in the HTTP response, so there is no account and no key. The plan: 0.10 USDC per explain call, paid in USDC on Solana; the catalog stays free.

  1. 01

    Ask

    Send the request as usual. Without payment, the API answers 402 Payment Required with the price in the PAYMENT-REQUIRED header.

  2. 02

    Pay and ask again

    Your client signs a USDC transfer of exactly amount to payTo and sends the same request again with it in X-PAYMENT.

  3. 03

    Get the answer and the receipt

    The transfer settles on Solana. The API answers 200 with the explanation and the settlement signature in X-PAYMENT-RESPONSE.

  • PAYMENT-REQUIREDresponse · 402

    JSON: scheme "exact", network "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" (mainnet), asset "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" (USDC), amount "100000" (0.10 USDC, 6 decimals), payTo and resource.

  • X-PAYMENTrequest

    The signed USDC transfer, base64, sent with the same request.

  • X-PAYMENT-RESPONSEresponse · 200

    The settlement transaction signature: the receipt.

MCP server and skill package

Use the HTTP API today (curl / fetch); the MCP server and skill package ship when the API leaves beta. The planned tools mirror the two endpoints: unstuck.explain(signature) and unstuck.errors(query). SKILL.md already describes the live HTTP calls.