{
  "openapi": "3.1.0",
  "info": {
    "title": "CryptoTopCard REST API",
    "version": "1.0.0",
    "description": "No-KYC virtual Visa & Mastercard cards funded with cryptocurrency. Bearer-token auth (ctk_live_...). Same auth tokens are usable on the MCP endpoint at /api/v1/mcp. Real x402 (scheme 'exact', USDC on Base) supported on POST /topups via header 'X-Payment-Mode: x402'.",
    "contact": { "url": "https://cryptotopcard.com/contact" },
    "license": { "name": "Proprietary", "url": "https://cryptotopcard.com/tos" }
  },
  "servers": [{ "url": "https://cryptotopcard.com/api/v1" }],
  "components": {
    "securitySchemes": {
      "bearer": { "type": "http", "scheme": "bearer", "bearerFormat": "ctk_live_<40hex>" }
    },
    "schemas": {
      "Envelope":     { "type": "object", "properties": { "ok": { "type": "boolean" }, "data": { "type": "object" } } },
      "Error":        { "type": "object", "properties": { "ok": { "type": "boolean", "const": false }, "error": { "type": "string" }, "message": { "type": "string" } } },
      "SignupResult": { "type": "object", "properties": { "user_id": { "type": "integer" }, "seed": { "type": "string" }, "token": { "type": "string" }, "token_prefix": { "type": "string" }, "scopes": { "type": "array", "items": { "type": "string" } } } },
      "Bin":          { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "network": { "type": "string", "enum": ["visa", "mastercard"] }, "category": { "type": "string" }, "tx_limit": { "type": "integer" }, "mo_limit": { "type": "integer" } } },
      "Coin":         { "type": "object", "properties": { "code": { "type": "string" }, "name": { "type": "string" }, "icon": { "type": "string" } } },
      "Topup":        { "type": "object", "properties": { "topup_id": { "type": "integer" }, "status": { "type": "string", "enum": ["pending", "completed", "cancelled"] }, "coin": { "type": "string" }, "net_credit_usd": { "type": "number" }, "gross_charge_usd": { "type": "number" }, "fee_usd": { "type": "number" }, "crypto_amount": { "type": "string" }, "deposit_address": { "type": "string" }, "expires_at": { "type": "string" } } },
      "Card":         { "type": "object", "properties": { "id": { "type": "integer" }, "label": { "type": "string" }, "bin_id": { "type": "string" }, "network": { "type": "string" }, "card_number": { "type": "string" }, "card_exp": { "type": "string" }, "card_cvv": { "type": "string" }, "balance": { "type": "number" }, "status": { "type": "string", "enum": ["active", "frozen", "deleted"] } } }
    }
  },
  "security": [{ "bearer": [] }],
  "paths": {
    "/coins": {
      "get": {
        "summary": "List supported cryptocurrencies for top-up",
        "security": [],
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "ok": { "type": "boolean" }, "data": { "type": "object", "properties": { "coins": { "type": "array", "items": { "$ref": "#/components/schemas/Coin" } } } } } } } } } }
      }
    },
    "/bins": {
      "get": {
        "summary": "List available BIN tiers (Visa Business, Mastercard World, etc.)",
        "security": [],
        "responses": { "200": { "description": "OK" } }
      }
    },
    "/auth/signup": {
      "post": {
        "summary": "Create a new anonymous account + first API token",
        "description": "Returns a 16-character seed phrase (only credential for account recovery) and a Bearer token. NEITHER CAN BE RECOVERED — persist them immediately.",
        "security": [],
        "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string" }, "scopes": { "type": "string" } } } } } },
        "responses": { "201": { "description": "Account created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SignupResult" } } } } }
      }
    },
    "/auth/login": {
      "post": {
        "summary": "Exchange a seed phrase for a fresh API token",
        "security": [],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["seed"], "properties": { "seed": { "type": "string" }, "name": { "type": "string" }, "scopes": { "type": "string" } } } } } },
        "responses": { "200": { "description": "Token issued" }, "401": { "description": "Invalid seed" } }
      }
    },
    "/me": {
      "get": {
        "summary": "Get the caller's account info + balance",
        "responses": { "200": { "description": "OK" }, "401": { "description": "Bearer required" } }
      }
    },
    "/topups": {
      "get": { "summary": "List the caller's top-ups", "responses": { "200": { "description": "OK" } } },
      "post": {
        "summary": "Create a crypto deposit request",
        "description": "Returns the exact crypto amount and deposit address. The 2% rail fee is grossed-up into the crypto amount; the NET USD amount you request is what lands on the balance after confirmation. x402: send header 'X-Payment-Mode: x402' to get an HTTP 402 with an 'accepts' block (scheme exact, USDC on Base); sign the EIP-3009 authorization and re-send the same request with the 'X-PAYMENT' header (gasless settle via our facilitator).",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["coin", "amount"], "properties": { "coin": { "type": "string", "example": "USDTTRC" }, "amount": { "type": "number", "description": "NET USD to credit", "minimum": 5, "maximum": 10000 } } } } } },
        "responses": { "201": { "description": "Top-up created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Topup" } } } } }
      }
    },
    "/topups/{id}": {
      "get": { "summary": "Get a top-up's status", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" }, "404": { "description": "Not found" } } }
    },
    "/topups/{id}/cancel": {
      "post": { "summary": "Cancel a pending top-up", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" } } }
    },
    "/cards": {
      "get": { "summary": "List the caller's cards (last4 only)", "responses": { "200": { "description": "OK" } } },
      "post": {
        "summary": "Issue a new virtual card",
        "description": "Debits CARD_FEE ($1.50) + amount from the account balance. Returns card_number, exp, CVV.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["bin_id", "amount"], "properties": { "bin_id": { "type": "string", "example": "471938" }, "amount": { "type": "number", "minimum": 150 }, "label": { "type": "string" } } } } } },
        "responses": { "201": { "description": "Card issued" } }
      }
    },
    "/cards/{id}": {
      "get": { "summary": "Get full card details (PAN, exp, CVV)", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" } } },
      "delete": { "summary": "Close the card and refund the remaining balance", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" } } }
    },
    "/cards/{id}/freeze":   { "post": { "summary": "Freeze a card (reversible)",   "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" } } } },
    "/cards/{id}/unfreeze": { "post": { "summary": "Unfreeze a frozen card",       "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" } } } },
    "/cards/{id}/topup":    { "post": { "summary": "Move funds from balance to card", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["amount"], "properties": { "amount": { "type": "number" } } } } } }, "responses": { "200": { "description": "OK" } } } },
    "/keys": {
      "get":  { "summary": "List the caller's API keys",                            "responses": { "200": { "description": "OK" } } },
      "post": { "summary": "Mint a new API key (returned ONCE in the response)",    "responses": { "201": { "description": "OK" } } }
    },
    "/keys/{id}": { "delete": { "summary": "Revoke an API key", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }], "responses": { "200": { "description": "OK" } } } }
  }
}
