PageSourceSearch

https://rwa-docs.tbook.com/assets/js/8ebd9e79.5f6efba6.js

js tbook.com collected 2026-10-02 07:25:26 UTC 7,936 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunktbook_docs=self.webpackChunktbook_docs||[]).push([["507"],{3890(e,t,n){n.r(t),n.d(t,{metadata:()=>s,default:()=>h,frontMatter:()=>d,contentTitle:()=>o,toc:()=>a,assets:()=>c});var s=JSON.parse('{"id":"getting-started/authentication","title":"Authentication & API Keys","description":"Every request authenticates with an API key. The key identifies your organization \u2014 there is no orgId parameter anywhere in the API; all resources (accounts, webhooks, events, analytics) are automatically scoped to the organization that owns the key.","source":"@site/docs/getting-started/authentication.mdx","sourceDirName":"getting-started","slug":"/getting-started/authentication","permalink":"/getting-started/authentication","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"title":"Authentication & API Keys","sidebar_position":3},"sidebar":"docs","previous":{"title":"Quickstart: first deposit in 30 minutes","permalink":"/getting-started/quickstart"},"next":{"title":"API Conventions","permalink":"/getting-started/conventions"}}'),i=n(4848),r=n(8453);let d={title:"Authentication & API Keys",sidebar_position:3},o="Authentication & API Keys",c={},a=[{value:"Sending the key",id:"sending-the-key",level:2},{value:"Key types",id:"key-types",level:2},{value:"Rate limits",id:"rate-limits",level:2},{value:"Issuance, rotation, revocation",id:"issuance-rotation-revocation",level:2},{value:"Errors",id:"errors",level:2}];function l(e){let t={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.header,{children:(0,i.jsx)(t.h1,{id:"authentication--api-keys",children:"Authentication & API Keys"})}),"\n",(0,i.jsxs)(t.p,{children:["Every request authenticates with an API key. ",(0,i.jsx)(t.strong,{children:"The key identifies your organization"})," \u2014 there is no ",(0,i.jsx)(t.code,{children:"orgId"})," parameter anywhere in the API; all resources (accounts, webhooks, events, analytics) are automatically scoped to the organization that owns the key."]}),"\n",(0,i.jsx)(t.h2,{id:"sending-the-key",children:"Sending the key"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:'# Preferred\ncurl -H "Authorization: Bearer tbk_secret_..." https://rwa-api.tbook.com/v1/accounts\n\n# Also accepted\ncurl -H "x-api-key: tbk_secret_..." https://rwa-api.tbook.com/v1/accounts\n'})}),"\n",(0,i.jsx)(t.h2,{id:"key-types",children:"Key types"}),"\n",(0,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{children:"Key"}),(0,i.jsx)(t.th,{children:"Prefix"}),(0,i.jsx)(t.th,{children:"Where it lives"}),(0,i.jsx)(t.th,{children:"Access"})]})}),(0,i.jsxs)(t.tbody,{children:[(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"Secret"}),(0,i.jsx)(t.td,{children:(0,i.jsx)(t.code,{children:"tbk_secret_"})}),(0,i.jsx)(t.td,{children:"Your servers only. Never in client code, repos, or logs."}),(0,i.jsx)(t.td,{children:"Everything: accounts, transaction building, webhooks, treasury, analytics"})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"Publishable"}),(0,i.jsx)(t.td,{children:(0,i.jsx)(t.code,{children:"tbk_pub_"})}),(0,i.jsx)(t.td,{children:"May ship in client-side code"}),(0,i.jsx)(t.td,{children:"Read catalogs & prices, build transactions"})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"Test"}),(0,i.jsx)(t.td,{children:(0,i.jsx)(t.code,{children:"tbk_test_"})}),(0,i.jsx)(t.td,{children:"Sandbox only"}),(0,i.jsx)(t.td,{children:"Everything, sandbox only"})]})]})]}),"\n",(0,i.jsxs)(t.p,{children:["Account data, positions, webhook management, treasury controls, and analytics always require a ",(0,i.jsx)(t.strong,{children:"secret"})," key (test keys have the same access on sandbox). Production keys never work on sandbox and vice versa."]}),"\n",(0,i.jsxs)(t.p,{children:["Public catalog reads (e.g. ",(0,i.jsx)(t.code,{children:"GET /v1/assets"}),", ",(0,i.jsx)(t.code,{children:"GET /v1/vaults/:vaultId/price"}),") also accept unauthenticated requests, but anonymous calls carry no organization context \u2014 no accounts, no intents, no idempotency deduplication."]}),"\n",(0,i.jsx)(t.h2,{id:"rate-limits",children:"Rate limits"}),"\n",(0,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{children:"Key"}),(0,i.jsx)(t.th,{children:"Limit"})]})}),(0,i.jsxs)(t.tbody,{children:[(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:(0,i.jsx)(t.code,{children:"tbk_secret_"})}),(0,i.jsx)(t.td,{children:"1000 requests/min"})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:(0,i.jsx)(t.code,{children:"tbk_pub_"})}),(0,i.jsx)(t.td,{children:"100 requests/min"})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:(0,i.jsx)(t.code,{children:"tbk_test_"})}),(0,i.jsx)(t.td,{children:"1000 requests/min (sandbox only)"})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"(no key)"}),(0,i.jsx)(t.td,{children:"30 requests/min"})]})]})]}),"\n",(0,i.jsxs)(t.p,{children:["Limits use fixed 60-second windows and are enforced ",(0,i.jsx)(t.strong,{children:"fleet-wide per API key"})," (per source IP for keyless calls) \u2014 the numbers above are exact regardless of how many instances serve your traffic. Responses include ",(0,i.jsx)(t.code,{children:"X-RateLimit-Limit"})," and ",(0,i.jsx)(t.code,{children:"X-RateLimit-Remaining"}),"; exceeding the limit returns ",(0,i.jsx)(t.code,{children:"429"})," with a ",(0,i.jsx)(t.code,{children:"Retry-After"})," header. Back off and retry \u2014 bursts are normal, sustained excess is not."]}),"\n",(0,i.jsx)(t.h2,{id:"issuance-rotation-revocation",children:"Issuance, rotation, revocation"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["Sandbox keys are issued during onboarding by your TBook contact; production keys after the ",(0,i.jsx)(t.a,{href:"/resources/onboarding-checklist",children:"onboarding checklist"})," is signed off."]}),"\n",(0,i.jsx)(t.li,{children:"Keys can be rotated at any time: a new key is issued, the old one keeps working for an agreed overlap window, then is revoked."}),"\n",(0,i.jsxs)(t.li,{children:["If a key is compromised, report it immediately \u2014 revocation is instant and all further requests with that key fail with ",(0,i.jsx)(t.code,{children:"authentication_error"}),"."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"TBook stores only a hash of each key. A lost key cannot be recovered, only replaced."}),"\n",(0,i.jsx)(t.h2,{id:"errors",children:"Errors"}),"\n",(0,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{children:"HTTP"}),(0,i.jsx)(t.th,{children:"Code"}),(0,i.jsx)(t.th,{children:"Meaning"})]})}),(0,i.jsxs)(t.tbody,{children:[(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"401"}),(0,i.jsx)(t.td,{children:(0,i.jsx)(t.code,{children:"authentication_error"})}),(0,i.jsx)(t.td,{children:"Missing, malformed, revoked, or wrong-environment key"})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:"403"}),(0,i.jsx)(t.td,{children:(0,i.jsx)(t.code,{children:"permission_denied"})}),(0,i.jsx)(t.td,{children:"Valid key, but this endpoint needs a secret key (or the resource requires different access)"})]})]})]})]})}function h(e={}){let{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453(e,t,n){n.d(t,{R:()=>d,x:()=>o});var s=n(6540);let i={},r=s.createContext(i);function d(e){let t=s.useContext(r);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:d(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.