[{"data":1,"prerenderedAt":389},["ShallowReactive",2],{"navigation":3,"docus_navigation_docs":147,"-docs-core-features-tokens":183,"-docs-core-features-tokens-surround":384},[4,130],{"title":5,"path":6,"stem":7,"children":8,"page":55},"Docs","\u002Fdocs","docs",[9,21,56,95,105,119],{"title":10,"path":11,"stem":12,"children":13,"icon":20},"Getting Started","\u002Fdocs\u002Fgetting-started","docs\u002F1.getting-started\u002F1.index",[14,16],{"title":15,"path":11,"stem":12},"Introduction",{"title":17,"path":18,"stem":19},"Quickstart","\u002Fdocs\u002Fgetting-started\u002Fquickstart","docs\u002F1.getting-started\u002F2.quickstart","i-lucide-rocket",{"title":22,"icon":23,"path":24,"stem":25,"children":26,"page":55},"Core Features","i-lucide-tag","\u002Fdocs\u002Fcore-features","docs\u002F2.core-features",[27,31,35,39,43,47,51],{"title":28,"path":29,"stem":30},"Audit Logs","\u002Fdocs\u002Fcore-features\u002Faudit-logs","docs\u002F2.core-features\u002Faudit-logs",{"title":32,"path":33,"stem":34},"Encryption","\u002Fdocs\u002Fcore-features\u002Fencryption","docs\u002F2.core-features\u002Fencryption",{"title":36,"path":37,"stem":38},"Environments","\u002Fdocs\u002Fcore-features\u002Fenvironments","docs\u002F2.core-features\u002Fenvironments",{"title":40,"path":41,"stem":42},"Projects","\u002Fdocs\u002Fcore-features\u002Fprojects","docs\u002F2.core-features\u002Fprojects",{"title":44,"path":45,"stem":46},"Teams","\u002Fdocs\u002Fcore-features\u002Fteams","docs\u002F2.core-features\u002Fteams",{"title":48,"path":49,"stem":50},"API Tokens","\u002Fdocs\u002Fcore-features\u002Ftokens","docs\u002F2.core-features\u002Ftokens",{"title":52,"path":53,"stem":54},"Variables","\u002Fdocs\u002Fcore-features\u002Fvariables","docs\u002F2.core-features\u002Fvariables",false,{"title":57,"icon":58,"path":59,"stem":60,"children":61},"CLI","i-lucide-terminal","\u002Fdocs\u002Fcli","docs\u002F3.cli\u002F2.index",[62,63,67,71,75,79,83,87,91],{"title":15,"path":59,"stem":60},{"title":64,"path":65,"stem":66},"Init","\u002Fdocs\u002Fcli\u002Finit","docs\u002F3.cli\u002F1.init",{"title":68,"path":69,"stem":70},"Run","\u002Fdocs\u002Fcli\u002Frun","docs\u002F3.cli\u002F3.run",{"title":72,"path":73,"stem":74},"Login and Logout","\u002Fdocs\u002Fcli\u002Flogin-logout","docs\u002F3.cli\u002F4.login-logout",{"title":76,"path":77,"stem":78},"Push and Pull","\u002Fdocs\u002Fcli\u002Fpush-pull","docs\u002F3.cli\u002F5.push-pull",{"title":80,"path":81,"stem":82},"Create","\u002Fdocs\u002Fcli\u002Fcreate","docs\u002F3.cli\u002F6.create",{"title":84,"path":85,"stem":86},"Config","\u002Fdocs\u002Fcli\u002Fconfig","docs\u002F3.cli\u002F7.config",{"title":88,"path":89,"stem":90},"Generate","\u002Fdocs\u002Fcli\u002Fgenerate","docs\u002F3.cli\u002F8.generate",{"title":92,"path":93,"stem":94},"Upgrade","\u002Fdocs\u002Fcli\u002Fupgrade","docs\u002F3.cli\u002F9.upgrade",{"title":96,"icon":97,"path":98,"stem":99,"children":100,"page":55},"Integrations","i-lucide-blocks","\u002Fdocs\u002Fintegrations","docs\u002F4.integrations",[101],{"title":102,"path":103,"stem":104},"Github","\u002Fdocs\u002Fintegrations\u002Fgithub","docs\u002F4.integrations\u002F1.github",{"title":106,"icon":107,"path":108,"stem":109,"children":110,"page":55},"Self-hosting","i-lucide-cloud","\u002Fdocs\u002Fself-hosting","docs\u002F5.self-hosting",[111,115],{"title":112,"path":113,"stem":114},"Deploy on Vercel","\u002Fdocs\u002Fself-hosting\u002Fvercel","docs\u002F5.self-hosting\u002F1.vercel",{"title":116,"path":117,"stem":118},"Environment variables","\u002Fdocs\u002Fself-hosting\u002Fenvironment-variables","docs\u002F5.self-hosting\u002F2.environment-variables",{"title":120,"path":121,"stem":122,"children":123,"icon":129},"Contributing","\u002Fdocs\u002Fcontributing","docs\u002F6.contributing\u002F1.index",[124,125],{"title":15,"path":121,"stem":122},{"title":126,"path":127,"stem":128},"Dev Setup","\u002Fdocs\u002Fcontributing\u002Fdev-setup","docs\u002F6.contributing\u002F2.dev-setup","i-lucide-heart-handshake",{"title":131,"path":132,"stem":133,"children":134,"page":55},"Blog","\u002Fblog","blog",[135,139,143],{"title":136,"path":137,"stem":138},"Introducing Shelve's Blog: Building in Public","\u002Fblog\u002Fintroducing-shelve-blog","blog\u002F01.introducing-shelve-blog",{"title":140,"path":141,"stem":142},"Announcing 2.0","\u002Fblog\u002Fannouncing-2.0","blog\u002F02.announcing-2.0",{"title":144,"path":145,"stem":146},"Crafting Clarity: Introducing the New Shelve Landing Page","\u002Fblog\u002Fnew-landing-page","blog\u002F03.new-landing-page",[148,152,161,172,175,179],{"title":10,"path":11,"stem":12,"children":149,"icon":20},[150,151],{"title":15,"path":11,"stem":12},{"title":17,"path":18,"stem":19},{"title":22,"icon":23,"path":24,"stem":25,"children":153,"page":55},[154,155,156,157,158,159,160],{"title":28,"path":29,"stem":30},{"title":32,"path":33,"stem":34},{"title":36,"path":37,"stem":38},{"title":40,"path":41,"stem":42},{"title":44,"path":45,"stem":46},{"title":48,"path":49,"stem":50},{"title":52,"path":53,"stem":54},{"title":57,"icon":58,"path":59,"stem":60,"children":162,"page":-1},[163,164,165,166,167,168,169,170,171],{"title":15,"path":59,"stem":60},{"title":64,"path":65,"stem":66},{"title":68,"path":69,"stem":70},{"title":72,"path":73,"stem":74},{"title":76,"path":77,"stem":78},{"title":80,"path":81,"stem":82},{"title":84,"path":85,"stem":86},{"title":88,"path":89,"stem":90},{"title":92,"path":93,"stem":94},{"title":96,"icon":97,"path":98,"stem":99,"children":173,"page":55},[174],{"title":102,"path":103,"stem":104},{"title":106,"icon":107,"path":108,"stem":109,"children":176,"page":55},[177,178],{"title":112,"path":113,"stem":114},{"title":116,"path":117,"stem":118},{"title":120,"path":121,"stem":122,"children":180,"icon":129},[181,182],{"title":15,"path":121,"stem":122},{"title":126,"path":127,"stem":128},{"id":184,"title":48,"body":185,"description":378,"extension":379,"meta":380,"navigation":381,"path":49,"seo":382,"stem":50,"__hash__":383},"docs\u002Fdocs\u002F2.core-features\u002Ftokens.md",{"type":186,"value":187,"toc":368},"minimark",[188,200,205,232,247,251,254,294,297,301,312,316,323,327,345,349],[189,190,191,192,199],"p",{},"API tokens let the CLI and any external system authenticate against Shelve. They are managed from your account settings at ",[193,194,198],"a",{"href":195,"rel":196},"https:\u002F\u002Fapp.shelve.cloud\u002Fuser\u002Ftokens",[197],"nofollow","app.shelve.cloud\u002Fuser\u002Ftokens",".",[201,202,204],"h2",{"id":203},"how-tokens-are-stored","How tokens are stored",[206,207,208,217,225],"ul",{},[209,210,211,212,216],"li",{},"The plaintext value is ",[213,214,215],"strong",{},"shown exactly once",", at creation. Copy it immediately — Shelve never stores it and cannot retrieve it later.",[209,218,219,220,224],{},"Only the SHA-256 hash of the token is written to the database, alongside a non-secret prefix (",[221,222,223],"code",{},"she_…"," — the first 12 characters). The prefix is what you see in the token list and in audit logs; it is useful for identifying a token without revealing it.",[209,226,227,228,231],{},"Lookups run in constant time (",[221,229,230],{},"timingSafeEqual"," on the hash), so there is no side channel that leaks bit-by-bit comparisons.",[233,234,236,237,240,241,246],"callout",{"type":235},"info","Tokens are produced from ",[221,238,239],{},"crypto.randomBytes(32)"," and encoded in ",[193,242,245],{"href":243,"rel":244},"https:\u002F\u002Fwww.crockford.com\u002Fbase32.html",[197],"Crockford base32",". They are 256 bits of entropy and cannot be brute-forced.",[201,248,250],{"id":249},"scoped-tokens","Scoped tokens",[189,252,253],{},"By default a token inherits your account's full access. You can narrow it when creating the token:",[255,256,257,274,282,286],"field-group",{},[258,259,262,263,266,267,270,271,199],"field",{"name":260,"type":261},"permissions","('read' | 'write')[]","At least one is required. ",[221,264,265],{},"read"," grants listing and fetching, ",[221,268,269],{},"write"," grants mutations. A read-only token that tries to POST a variable receives ",[221,272,273],{},"403 Token missing 'write' permission",[258,275,278,279,199],{"name":276,"type":277},"teamIds","number[]","Restrict the token to one or more teams. Requests targeting any other team return ",[221,280,281],{},"403 Token not authorized for this team",[258,283,285],{"name":284,"type":277},"projectIds","Restrict the token to specific projects within the allowed teams.",[258,287,289,290,293],{"name":288,"type":277},"environmentIds","Restrict the token to specific environments. Useful for CI tokens that should only read ",[221,291,292],{},"production"," secrets, for example.",[189,295,296],{},"Scope enforcement happens server-side in a dedicated middleware; the token can never outgrow the scope it was issued with.",[201,298,300],{"id":299},"expiry","Expiry",[189,302,303,304,307,308,311],{},"Every token may carry an ",[221,305,306],{},"expiresAt",". After that date the token is refused with ",[221,309,310],{},"401 Token expired"," even before it is hashed and matched. Rotating a short-lived CI token is as simple as creating a new one; no restart or config push is required.",[201,313,315],{"id":314},"ip-allowlist","IP allowlist",[189,317,318,319,322],{},"Optionally attach a list of CIDR blocks to a token. Requests originating outside those blocks are rejected with ",[221,320,321],{},"401 Token not authorized for this network",". Both IPv4 and IPv6 notations are supported.",[201,324,326],{"id":325},"audit-trail","Audit trail",[189,328,329,330,333,334,337,338,341,342,199],{},"Token lifecycle events (",[221,331,332],{},"token.create",", ",[221,335,336],{},"token.delete",") and every authenticated request surface in ",[193,339,340],{"href":29},"audit logs"," with the token prefix, actor, IP, and user agent. When something looks wrong, revoke the token from the UI — the hash is deleted and the next request using it returns ",[221,343,344],{},"401",[201,346,348],{"id":347},"sending-tokens","Sending tokens",[189,350,351,352,355,356,359,360,363,364,367],{},"The CLI and any integration should send the token as an ",[221,353,354],{},"Authorization: Bearer \u003Ctoken>"," header. The legacy ",[221,357,358],{},"Cookie: authToken=…"," path still works for older CLI builds but returns ",[221,361,362],{},"Deprecation: true"," \u002F ",[221,365,366],{},"Sunset: Wed, 01 Jul 2026 00:00:00 GMT"," response headers — migrate clients before that date.",{"title":369,"searchDepth":370,"depth":370,"links":371},"",2,[372,373,374,375,376,377],{"id":203,"depth":370,"text":204},{"id":249,"depth":370,"text":250},{"id":299,"depth":370,"text":300},{"id":314,"depth":370,"text":315},{"id":325,"depth":370,"text":326},{"id":347,"depth":370,"text":348},"Create, scope, and revoke API tokens for the CLI and integrations.","md",{},true,{"title":48,"description":378},"s7SYYDRO4jkfvFrJfC08A0xQxoW6gbGhqUciYlcQXbg",[385,387],{"title":44,"path":45,"stem":46,"description":386,"children":-1},"Learn more about teams in Shelve",{"title":52,"path":53,"stem":54,"description":388,"children":-1},"Learn more about variables in Shelve",1776787533560]