{
  "openapi": "3.1.0",
  "info": {
    "title": "Turnqey API",
    "version": "2026.04.1",
    "summary": "Cryptoasset infrastructure for Registered Investment Advisors.",
    "description": "Unified API surface across the Turnqey product line - Turnqey API (accounts, transactions, balances, integrity), QScore (market data, scoring, portfolios), TAIP (tax reporting), Q-Sim, ROI Calculator, Qeychain (wallet tracking), and ByAllAccounts aggregation.",
    "contact": {
      "name": "Turnqey Developer Support",
      "email": "support@turnqey.xyz",
      "url": "https://docs.turnqey.xyz/"
    }
  },
  "servers": [
    {
      "url": "https://api.turnqey.xyz",
      "description": "Turnqey API - Production (use /v1/api/* paths)"
    },
    {
      "url": "https://sandbox.turnqey.xyz",
      "description": "Sandbox"
    }
  ],
  "tags": [
    {
      "name": "Auth",
      "description": "Bearer-token issuance for the Turnqey API."
    },
    {
      "name": "Accounts",
      "description": "Cryptoasset accounts, identity lookups, transactions, and balances."
    },
    {
      "name": "Integrity",
      "description": "Data checksum endpoints used for partner reconciliation."
    },
    {
      "name": "Cryptoassets",
      "description": "Market data, prices, and reference info for tracked cryptocurrencies."
    },
    {
      "name": "QScore",
      "description": "Portfolio risk and credit-style scoring (Q, F, R scores)."
    },
    {
      "name": "Portfolios",
      "description": "Cryptocurrency portfolio CRUD with weighted allocations."
    },
    {
      "name": "Status",
      "description": "Service status and health probes."
    },
    {
      "name": "ByAllAccounts",
      "description": "Aggregated financial accounts and portfolio summaries."
    },
    {
      "name": "TAIP",
      "description": "Cryptoasset tax reporting and Form 8949 generation."
    },
    {
      "name": "Qeychain",
      "description": "Wallet-address-based holdings, cost basis, IRS Schedule 1."
    },
    {
      "name": "Q-Sim",
      "description": "Portfolio simulation and scenario modeling."
    },
    {
      "name": "ROI",
      "description": "Investment ROI and benchmark projections."
    }
  ],
  "security": [
    {
      "Bearer": []
    }
  ],
  "paths": {
    "/v1/api/token": {
      "post": {
        "operationId": "createToken",
        "tags": [
          "Auth"
        ],
        "summary": "Generate authentication token",
        "description": "Creates a new JWT token using client credentials. Tokens are valid for one hour - call this endpoint hourly to rotate.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "clientId": "tnq_client_01HVYX",
                "clientSecret": "••••••••"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token issued",
            "content": {
              "application/json": {
                "example": {
                  "isError": false,
                  "message": "Success",
                  "result": {
                    "accessToken": "eyJhbGciOiJIUzI1Ni…",
                    "expiresIn": 3600,
                    "tokenType": "Bearer"
                  },
                  "statusCode": 200
                }
              }
            }
          },
          "401": {
            "description": "Invalid client credentials."
          }
        },
        "security": []
      }
    },
    "/v1/api/account/collection/{collectionId}": {
      "get": {
        "operationId": "getAccountByCollection",
        "tags": [
          "Accounts"
        ],
        "summary": "Get account collection by ID",
        "description": "Retrieves account information for a specific collection identified by its UUID.",
        "parameters": [
          {
            "name": "collectionId",
            "in": "path",
            "required": true,
            "description": "UUID of the account collection.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Account collection",
            "content": {
              "application/json": {
                "example": {
                  "isError": false,
                  "message": "Success",
                  "result": {
                    "accountId": "12345678-e89b-12d3-a456-426614174000",
                    "collectionId": "98765432-e89b-12d3-a456-426614174000",
                    "platform": "coinbase",
                    "createdOn": "2024-08-01T00:00:00Z"
                  },
                  "statusCode": 200
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - bearer token missing or invalid."
          },
          "404": {
            "description": "Collection not found."
          }
        }
      }
    },
    "/v1/api/account/identity/{identity}": {
      "get": {
        "operationId": "getAccountByIdentity",
        "tags": [
          "Accounts"
        ],
        "summary": "Get account by identity",
        "description": "Retrieves account information for a specific identity string (e.g. external advisor identifier).",
        "parameters": [
          {
            "name": "identity",
            "in": "path",
            "required": true,
            "description": "Identity string used by the partner system.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Account record",
            "content": {
              "application/json": {
                "example": {
                  "isError": false,
                  "message": "Success",
                  "result": {
                    "accountId": "12345678-e89b-12d3-a456-426614174000",
                    "identity": "advisor_42",
                    "platform": "kraken"
                  },
                  "statusCode": 200
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized."
          },
          "404": {
            "description": "Identity not found."
          }
        }
      }
    },
    "/v1/api/account/{accountId}/transactions": {
      "get": {
        "operationId": "getAccountTransactions",
        "tags": [
          "Accounts"
        ],
        "summary": "Get account transactions",
        "description": "Retrieves transaction history for a specific account identified by its UUID.",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "description": "UUID of the account.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Inclusive start date (ISO-8601).",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Inclusive end date (ISO-8601).",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Transaction history",
            "content": {
              "application/json": {
                "example": {
                  "isError": false,
                  "message": "Success",
                  "result": {
                    "transactions": [
                      {
                        "transactionId": "tx_01HVYX",
                        "symbol": "BTC",
                        "direction": "buy",
                        "amount": "0.5",
                        "price": "49000.00",
                        "timestamp": "2024-09-12T15:04:05Z"
                      }
                    ]
                  },
                  "statusCode": 200
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized."
          }
        }
      }
    },
    "/v1/api/account/{accountId}/balances": {
      "get": {
        "operationId": "getAccountBalances",
        "tags": [
          "Accounts"
        ],
        "summary": "Get account balances",
        "description": "Retrieves current balances for a specific account identified by its UUID.",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "description": "UUID of the account.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "forceRefresh",
            "in": "query",
            "required": false,
            "description": "Force a refresh from the source if cached data is older than 30 minutes.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Account balances",
            "content": {
              "application/json": {
                "example": {
                  "isError": false,
                  "message": "Success",
                  "result": {
                    "balances": [
                      {
                        "symbol": "BTC",
                        "balance": "0.5",
                        "costBasis": "24500.00",
                        "marketValue": "25000.00",
                        "realizedGainLoss": "500.00",
                        "unrealizedGainLoss": "500.00"
                      }
                    ],
                    "lastUpdatedOn": "2024-09-12T15:04:05Z",
                    "marketValue": "25000.00",
                    "realizedGainLoss": "500.00",
                    "unrealizedGainLoss": "500.00"
                  },
                  "statusCode": 200
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized."
          },
          "422": {
            "description": "Unprocessable entity."
          }
        }
      }
    },
    "/v1/api/checksum": {
      "get": {
        "operationId": "getChecksum",
        "tags": [
          "Integrity"
        ],
        "summary": "Get data checksum",
        "description": "Retrieves a checksum for data verification, filtered by platform, collection, or identity.",
        "parameters": [
          {
            "name": "platform",
            "in": "query",
            "required": false,
            "description": "Filter by source platform (e.g. coinbase, kraken).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "collectionId",
            "in": "query",
            "required": false,
            "description": "Filter by account collection.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "identity",
            "in": "query",
            "required": false,
            "description": "Filter by external identity string.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Checksum payload",
            "content": {
              "application/json": {
                "example": {
                  "isError": false,
                  "message": "Success",
                  "result": {
                    "checksum": "f3a1c0b9d4e8…",
                    "computedAt": "2024-09-12T15:04:05Z",
                    "rowCount": 4218
                  },
                  "statusCode": 200
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized."
          }
        }
      }
    },
    "/api/crypto-data/{symbols}": {
      "get": {
        "operationId": "getCryptoData",
        "tags": [
          "Cryptoassets"
        ],
        "summary": "Get cryptocurrency market data",
        "description": "Fetch current market data for the specified cryptocurrencies. `symbols` is a comma-separated list of CoinGecko IDs (e.g. `bitcoin,ethereum,solana`).",
        "parameters": [
          {
            "name": "symbols",
            "in": "path",
            "required": true,
            "description": "Comma-separated list of cryptocurrency symbols.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Array of market data records",
            "content": {
              "application/json": {
                "example": [
                  {
                    "id": 1,
                    "symbol": "BTC",
                    "name": "Bitcoin",
                    "price": 64321.12,
                    "marketCap": 1268000000000,
                    "marketCapRank": 1,
                    "circulatingSupply": 19712000,
                    "totalSupply": 21000000,
                    "maxSupply": 21000000,
                    "volume24h": 32100000000,
                    "volatility": 0.62,
                    "communityScore": 87.4,
                    "developerScore": 92.1,
                    "liquidityScore": 95,
                    "publicInterestScore": 88.6,
                    "lastUpdated": "2024-09-12T15:04:05Z"
                  }
                ]
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded."
          },
          "500": {
            "description": "Server error."
          }
        }
      }
    },
    "/api/calculate-portfolio-score": {
      "post": {
        "operationId": "calculatePortfolioScore",
        "tags": [
          "QScore"
        ],
        "summary": "Calculate portfolio Q Score",
        "description": "Calculate the overall Q Score, F Score, and R Score for a cryptocurrency portfolio described by per-asset allocation percentages.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "btcAllocation": 60,
                "ethAllocation": 30,
                "solAllocation": 10
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Portfolio Q Score result",
            "content": {
              "application/json": {
                "example": {
                  "qScore": 82.4,
                  "fScore": 78.1,
                  "rScore": 64.9,
                  "allocation": {
                    "BTC": 60,
                    "ETH": 30,
                    "SOL": 10
                  },
                  "breakdown": {
                    "BTC": 88,
                    "ETH": 79,
                    "SOL": 65
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing score data or invalid allocations."
          },
          "500": {
            "description": "Server error."
          }
        }
      }
    },
    "/api/scores": {
      "get": {
        "operationId": "getScores",
        "tags": [
          "QScore"
        ],
        "summary": "Get all cryptocurrency Q scores",
        "description": "Retrieve Q scores, F scores, and R scores for all tracked cryptocurrencies.",
        "responses": {
          "200": {
            "description": "Per-asset score table",
            "content": {
              "application/json": {
                "example": [
                  {
                    "symbol": "BTC",
                    "qScore": 88,
                    "fScore": 90.1,
                    "rScore": 70.2
                  },
                  {
                    "symbol": "ETH",
                    "qScore": 79,
                    "fScore": 81.5,
                    "rScore": 64
                  }
                ]
              }
            }
          },
          "500": {
            "description": "Server error."
          }
        }
      }
    },
    "/api/status": {
      "get": {
        "operationId": "getStatus",
        "tags": [
          "Status"
        ],
        "summary": "Get API status and health information",
        "description": "Check API connectivity, rate limits, and system status.",
        "responses": {
          "200": {
            "description": "Service status",
            "content": {
              "application/json": {
                "example": {
                  "status": "ok",
                  "uptimeSeconds": 481239,
                  "rateLimitRemaining": 1000,
                  "version": "2026.04.1"
                }
              }
            }
          }
        }
      }
    },
    "/api/portfolios": {
      "get": {
        "operationId": "listPortfolios",
        "tags": [
          "Portfolios"
        ],
        "summary": "Get all portfolios",
        "description": "Retrieve all user portfolios with their allocations.",
        "responses": {
          "200": {
            "description": "Portfolio list",
            "content": {
              "application/json": {
                "example": [
                  {
                    "id": "pf_01HVYX",
                    "name": "Conservative Crypto",
                    "allocations": {
                      "BTC": 70,
                      "ETH": 30
                    }
                  }
                ]
              }
            }
          },
          "401": {
            "description": "Unauthorized."
          }
        }
      },
      "post": {
        "operationId": "createPortfolio",
        "tags": [
          "Portfolios"
        ],
        "summary": "Create a new portfolio",
        "description": "Create a new cryptocurrency portfolio.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "name": "Aggressive Growth",
                "allocations": {
                  "BTC": 50,
                  "ETH": 30,
                  "SOL": 20
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "example": {
                  "id": "pf_01HVZY",
                  "name": "Aggressive Growth",
                  "allocations": {
                    "BTC": 50,
                    "ETH": 30,
                    "SOL": 20
                  }
                }
              }
            }
          },
          "400": {
            "description": "Allocations must sum to 100."
          }
        }
      }
    },
    "/api/portfolios/{id}": {
      "get": {
        "operationId": "getPortfolio",
        "tags": [
          "Portfolios"
        ],
        "summary": "Get portfolio by ID",
        "description": "Retrieve a specific portfolio with its allocations.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Portfolio identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Portfolio detail",
            "content": {
              "application/json": {
                "example": {
                  "id": "pf_01HVYX",
                  "name": "Conservative Crypto",
                  "allocations": {
                    "BTC": 70,
                    "ETH": 30
                  },
                  "qScore": 82.4
                }
              }
            }
          },
          "404": {
            "description": "Portfolio not found."
          }
        }
      },
      "put": {
        "operationId": "updatePortfolio",
        "tags": [
          "Portfolios"
        ],
        "summary": "Update portfolio",
        "description": "Update an existing portfolio (replaces allocations).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Portfolio identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "name": "Conservative Crypto v2",
                "allocations": {
                  "BTC": 65,
                  "ETH": 35
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "example": {
                  "id": "pf_01HVYX",
                  "name": "Conservative Crypto v2",
                  "allocations": {
                    "BTC": 65,
                    "ETH": 35
                  }
                }
              }
            }
          },
          "404": {
            "description": "Portfolio not found."
          }
        }
      },
      "delete": {
        "operationId": "deletePortfolio",
        "tags": [
          "Portfolios"
        ],
        "summary": "Delete portfolio",
        "description": "Delete a portfolio and its allocations.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Portfolio identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Portfolio deleted."
          },
          "404": {
            "description": "Portfolio not found."
          }
        }
      }
    },
    "/portfolio/summary": {
      "get": {
        "operationId": "getPortfolioSummary",
        "tags": [
          "ByAllAccounts"
        ],
        "summary": "Portfolio summary",
        "description": "Returns an aggregated portfolio summary across linked institutions.",
        "parameters": [
          {
            "name": "account_id",
            "in": "query",
            "required": false,
            "description": "Restrict the summary to a single linked account.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Aggregated portfolio summary",
            "content": {
              "application/json": {
                "example": {
                  "btc_balance": "2.847 BTC",
                  "usd_value": "$274,318",
                  "exchanges": [
                    "Coinbase",
                    "Kraken"
                  ],
                  "sync_status": "live"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid bearer token."
          }
        }
      }
    },
    "/qscore/evaluate": {
      "post": {
        "operationId": "evaluateQScore",
        "tags": [
          "QScore"
        ],
        "summary": "Evaluate a QScore for a linked account",
        "description": "Compute a QScore for a portfolio snapshot already linked via ByAllAccounts.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "account_id": "acct_01HVYX",
                "as_of_date": "2026-04-15"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "QScore result",
            "content": {
              "application/json": {
                "example": {
                  "score": 812,
                  "grade": "A+",
                  "btc_weight": "64%",
                  "risk_level": "aggressive"
                }
              }
            }
          },
          "400": {
            "description": "Malformed request body."
          }
        }
      }
    },
    "/taip/gains-report": {
      "get": {
        "operationId": "getGainsReport",
        "tags": [
          "TAIP"
        ],
        "summary": "Gains report",
        "description": "Realized and unrealized gains for an account, ready for Form 8949.",
        "parameters": [
          {
            "name": "tax_year",
            "in": "query",
            "required": true,
            "description": "Tax year (e.g. 2026).",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Gains report",
            "content": {
              "application/json": {
                "example": {
                  "asset": "BTC",
                  "net_gains": "$98,140",
                  "transactions": 312,
                  "form_8949": "ready"
                }
              }
            }
          }
        }
      }
    },
    "/qeychain/wallets": {
      "get": {
        "operationId": "listWallets",
        "tags": [
          "Qeychain"
        ],
        "summary": "List tracked wallets",
        "description": "Returns a paginated list of wallets tracked under your organization.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size (default 50, max 200).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor returned by a previous page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated wallet list",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "address": "bc1qxy2k...",
                      "chain": "bitcoin",
                      "btc_holdings": "1.204 BTC",
                      "cost_basis": "$51,200",
                      "unrealized_pnl": "+$64,918"
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          }
        }
      }
    },
    "/qsim/simulate": {
      "post": {
        "operationId": "runSimulation",
        "tags": [
          "Q-Sim"
        ],
        "summary": "Run a portfolio simulation",
        "description": "Run scenario projections (bull/base/bear) over a target horizon.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "portfolio": [
                  {
                    "symbol": "BTC",
                    "weight": 0.6
                  },
                  {
                    "symbol": "ETH",
                    "weight": 0.4
                  }
                ],
                "horizon_years": 5,
                "scenarios": [
                  "bull",
                  "base",
                  "bear"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Simulation result",
            "content": {
              "application/json": {
                "example": {
                  "scenarios": [
                    {
                      "name": "bull",
                      "cagr": "21.4%",
                      "terminal_usd": "$264,118"
                    },
                    {
                      "name": "base",
                      "cagr": "9.2%",
                      "terminal_usd": "$155,402"
                    },
                    {
                      "name": "bear",
                      "cagr": "-3.1%",
                      "terminal_usd": "$85,431"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/roi/projection": {
      "get": {
        "operationId": "getRoiProjection",
        "tags": [
          "ROI"
        ],
        "summary": "ROI projection",
        "description": "Single-shot ROI projection given a principal and horizon.",
        "parameters": [
          {
            "name": "principal_usd",
            "in": "query",
            "required": true,
            "description": "Principal amount in USD.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "horizon_years",
            "in": "query",
            "required": true,
            "description": "Investment horizon in years.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ROI projection",
            "content": {
              "application/json": {
                "example": {
                  "principal_usd": 100000,
                  "horizon_years": 10,
                  "terminal_usd": "$248,400",
                  "cagr": "9.5%",
                  "benchmark_diff": "+2.1%"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "Bearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "JWT bearer token issued by POST /v1/api/token."
      }
    }
  }
}
