[{"data":1,"prerenderedAt":698},["ShallowReactive",2],{"docs:\u002Fdocs\u002Fapi\u002Fprovisioning":3,"docs:nav":652},{"id":4,"title":5,"badge":6,"body":7,"description":643,"extension":644,"meta":645,"navigation":646,"order":41,"path":647,"section":648,"seo":649,"stem":650,"__hash__":651},"docs\u002Fdocs\u002Fapi\u002Fprovisioning.md","Credentials",null,{"type":8,"value":9,"toc":636},"minimark",[10,14,19,27,64,73,131,196,207,212,278,285,289,292,326,334,346,350,353,384,412,418,422,483,489,493,500,556,567,571,578,625,632],[11,12,13],"p",{},"Your credential is your account. There is no separate account resource, no username, and no\npassword.",[15,16,18],"h2",{"id":17},"post-authprovision","POST \u002Fauth\u002Fprovision",[11,20,21,22,26],{},"Creates a new ed25519 keypair and registers it as an active account. ",[23,24,25],"strong",{},"This is the only endpoint\nthat requires no authentication",", since you have nothing to sign with yet.",[28,29,34],"pre",{"className":30,"code":31,"language":32,"meta":33,"style":33},"language-bash shiki shiki-themes github-dark-default github-dark-default","curl -X POST \"$TESSERA_API\u002Fauth\u002Fprovision\"\n","bash","",[35,36,37],"code",{"__ignoreMap":33},[38,39,42,46,50,54,57,61],"span",{"class":40,"line":41},"line",1,[38,43,45],{"class":44},"sAxfE","curl",[38,47,49],{"class":48},"sEQcL"," -X",[38,51,53],{"class":52},"skZ57"," POST",[38,55,56],{"class":52}," \"",[38,58,60],{"class":59},"sb7RM","$TESSERA_API",[38,62,63],{"class":52},"\u002Fauth\u002Fprovision\"\n",[11,65,66,69,70],{},[23,67,68],{},"Response"," — ",[35,71,72],{},"201 Created",[28,74,78],{"className":75,"code":76,"language":77,"meta":33,"style":33},"language-json shiki shiki-themes github-dark-default github-dark-default","{\n  \"appID\": \"Aq3fZm9rLXRl\",\n  \"appKey\": \"kR8vN2pQ...\",\n  \"credential\": \"Aq3fZm9rLXRlc3QtY3JlZGVudGlhbC1oZXJlLW9r=\"\n}\n","json",[35,79,80,85,101,114,125],{"__ignoreMap":33},[38,81,82],{"class":40,"line":41},[38,83,84],{"class":59},"{\n",[38,86,88,92,95,98],{"class":40,"line":87},2,[38,89,91],{"class":90},"sV7Mv","  \"appID\"",[38,93,94],{"class":59},": ",[38,96,97],{"class":52},"\"Aq3fZm9rLXRl\"",[38,99,100],{"class":59},",\n",[38,102,104,107,109,112],{"class":40,"line":103},3,[38,105,106],{"class":90},"  \"appKey\"",[38,108,94],{"class":59},[38,110,111],{"class":52},"\"kR8vN2pQ...\"",[38,113,100],{"class":59},[38,115,117,120,122],{"class":40,"line":116},4,[38,118,119],{"class":90},"  \"credential\"",[38,121,94],{"class":59},[38,123,124],{"class":52},"\"Aq3fZm9rLXRlc3QtY3JlZGVudGlhbC1oZXJlLW9r=\"\n",[38,126,128],{"class":40,"line":127},5,[38,129,130],{"class":59},"}\n",[132,133,134,147],"table",{},[135,136,137],"thead",{},[138,139,140,144],"tr",{},[141,142,143],"th",{},"Field",[141,145,146],{},"Description",[148,149,150,161,179],"tbody",{},[138,151,152,158],{},[153,154,155],"td",{},[35,156,157],{},"appID",[153,159,160],{},"A short, non-secret identifier derived from the public key. Safe to log, useful in support requests.",[138,162,163,168],{},[153,164,165],{},[35,166,167],{},"appKey",[153,169,170,173,174,178],{},[23,171,172],{},"The private key."," 64 bytes, base64url, ",[175,176,177],"em",{},"unpadded",". Returned exactly once and never recoverable.",[138,180,181,186],{},[153,182,183],{},[35,184,185],{},"credential",[153,187,188,189,192,193,195],{},"The public key. 32 bytes, base64url, ",[175,190,191],{},"padded",". Your account identifier and the ",[35,194,185],{}," query parameter.",[197,198,201],"app-callout",{"title":199,"tone":200},"Store `appKey` before you store data","warn",[11,202,203,204,206],{},"There is no recovery flow. We hold only the public half. If ",[35,205,167],{}," is lost, every object under it\nbecomes unreachable — to you and to us. It is also the account itself, so it cannot be rotated\nwithout re-registering your objects under a new credential.",[11,208,209],{},[23,210,211],{},"Errors",[132,213,214,227],{},[135,215,216],{},[138,217,218,221,224],{},[141,219,220],{},"Status",[141,222,223],{},"Body",[141,225,226],{},"Cause",[148,228,229,248,263],{},[138,230,231,236,241],{},[153,232,233],{},[35,234,235],{},"405",[153,237,238],{},[35,239,240],{},"method not allowed",[153,242,243,244,247],{},"Not a ",[35,245,246],{},"POST",".",[138,249,250,255,260],{},[153,251,252],{},[35,253,254],{},"429",[153,256,257],{},[35,258,259],{},"{\"error\": \"rate limited: max 5 keys per hour\"}",[153,261,262],{},"More than 5 provisions from one source address within an hour.",[138,264,265,270,275],{},[153,266,267],{},[35,268,269],{},"500",[153,271,272],{},[35,273,274],{},"{\"error\": \"...\"}",[153,276,277],{},"Key generation failed.",[11,279,280,281,284],{},"The rate limit is per source address and honours ",[35,282,283],{},"X-Forwarded-For",". If you need many credentials —\none per tenant, say — request a bulk arrangement rather than working around the limit.",[15,286,288],{"id":287},"get-authcheck","GET \u002Fauth\u002Fcheck",[11,290,291],{},"Verifies that a credential is provisioned, active, and that your signature is correct. The cheapest\nway to test a signing implementation.",[28,293,295],{"className":30,"code":294,"language":32,"meta":33,"style":33},"curl -sD - -o \u002Fdev\u002Fnull \"$TESSERA_API\u002Fauth\u002Fcheck?$AUTH\"\n",[35,296,297],{"__ignoreMap":33},[38,298,299,301,304,307,310,313,315,317,320,323],{"class":40,"line":41},[38,300,45],{"class":44},[38,302,303],{"class":48}," -sD",[38,305,306],{"class":52}," -",[38,308,309],{"class":48}," -o",[38,311,312],{"class":52}," \u002Fdev\u002Fnull",[38,314,56],{"class":52},[38,316,60],{"class":59},[38,318,319],{"class":52},"\u002Fauth\u002Fcheck?",[38,321,322],{"class":59},"$AUTH",[38,324,325],{"class":52},"\"\n",[11,327,328,69,330,333],{},[23,329,68],{},[35,331,332],{},"204 No Content"," on success. No body.",[11,335,336,339,340,345],{},[35,337,338],{},"401"," with a plain-text reason otherwise; see ",[341,342,344],"a",{"href":343},"\u002Fdocs\u002Fauthentication#failure-modes","Authentication","\nfor the full list of reasons and what each one means.",[15,347,349],{"id":348},"delete-authrevoke","DELETE \u002Fauth\u002Frevoke",[11,351,352],{},"Revokes a credential. Effective immediately — the next request using it fails.",[28,354,356],{"className":30,"code":355,"language":32,"meta":33,"style":33},"curl -X DELETE \"$TESSERA_API\u002Fauth\u002Frevoke?credential=$TARGET&$AUTH\"\n",[35,357,358],{"__ignoreMap":33},[38,359,360,362,364,367,369,371,374,377,380,382],{"class":40,"line":41},[38,361,45],{"class":44},[38,363,49],{"class":48},[38,365,366],{"class":52}," DELETE",[38,368,56],{"class":52},[38,370,60],{"class":59},[38,372,373],{"class":52},"\u002Fauth\u002Frevoke?credential=",[38,375,376],{"class":59},"$TARGET",[38,378,379],{"class":52},"&",[38,381,322],{"class":59},[38,383,325],{"class":52},[132,385,386,398],{},[135,387,388],{},[138,389,390,393,396],{},[141,391,392],{},"Parameter",[141,394,395],{},"Required",[141,397,146],{},[148,399,400],{},[138,401,402,406,409],{},[153,403,404],{},[35,405,185],{},[153,407,408],{},"yes",[153,410,411],{},"The credential to revoke, padded base64url.",[11,413,414,69,416,247],{},[23,415,68],{},[35,417,332],{},[11,419,420],{},[23,421,211],{},[132,423,424,434],{},[135,425,426],{},[138,427,428,430,432],{},[141,429,220],{},[141,431,223],{},[141,433,226],{},[148,435,436,454,468],{},[138,437,438,443,448],{},[153,439,440],{},[35,441,442],{},"400",[153,444,445],{},[35,446,447],{},"missing credential",[153,449,450,451,453],{},"The ",[35,452,185],{}," parameter was absent.",[138,455,456,460,465],{},[153,457,458],{},[35,459,338],{},[153,461,462],{},[175,463,464],{},"(various)",[153,466,467],{},"The signing credential was not accepted.",[138,469,470,474,478],{},[153,471,472],{},[35,473,235],{},[153,475,476],{},[35,477,240],{},[153,479,243,480,247],{},[35,481,482],{},"DELETE",[197,484,486],{"title":485,"tone":200},"Revocation stops access, not storage",[11,487,488],{},"Revoking a credential stops authorisation. It does not delete your objects, and the storage\ncontracts covering their shards remain funded until they expire. If you intend to remove data,\ndelete the objects first and then revoke — in that order, because after revocation you can no longer\nissue the deletes.",[15,490,492],{"id":491},"account-state","Account state",[11,494,495,496,499],{},"Internally a credential is in one of four states. Only ",[35,497,498],{},"active"," authorises requests:",[132,501,502,512],{},[135,503,504],{},[138,505,506,509],{},[141,507,508],{},"State",[141,510,511],{},"Behaviour",[148,513,514,527,536,546],{},[138,515,516,521],{},[153,517,518],{},[35,519,520],{},"provisioned",[153,522,523,524,247],{},"Created but not yet activated. Requests are refused as ",[35,525,526],{},"unknown credential",[138,528,529,533],{},[153,530,531],{},[35,532,498],{},[153,534,535],{},"Normal operation.",[138,537,538,543],{},[153,539,540],{},[35,541,542],{},"suspended",[153,544,545],{},"Temporarily refused, for example for non-payment. Data is retained.",[138,547,548,553],{},[153,549,550],{},[35,551,552],{},"revoked",[153,554,555],{},"Permanently refused. The record is kept so the key cannot be re-provisioned.",[11,557,558,559,562,563,566],{},"A refused request returns ",[35,560,561],{},"401 unknown credential"," regardless of which non-active state applies —\nthe API does not distinguish, deliberately, since telling an unauthenticated caller ",[175,564,565],{},"why"," a key is\nrefused is more useful to an attacker than to you.",[15,568,570],{"id":569},"caps","Caps",[11,572,573,574,577],{},"Each credential carries caps for maximum stored bytes, daily read and write volume, and monthly\nspend. Requests that would exceed a storage cap are refused with ",[35,575,576],{},"402 Payment Required",":",[28,579,581],{"className":75,"code":580,"language":77,"meta":33,"style":33},"{\n  \"error\": \"storage cap exceeded\",\n  \"capBytes\": 5497558138880,\n  \"incomingBytes\": 62914560\n}\n",[35,582,583,587,599,611,621],{"__ignoreMap":33},[38,584,585],{"class":40,"line":41},[38,586,84],{"class":59},[38,588,589,592,594,597],{"class":40,"line":87},[38,590,591],{"class":90},"  \"error\"",[38,593,94],{"class":59},[38,595,596],{"class":52},"\"storage cap exceeded\"",[38,598,100],{"class":59},[38,600,601,604,606,609],{"class":40,"line":103},[38,602,603],{"class":90},"  \"capBytes\"",[38,605,94],{"class":59},[38,607,608],{"class":48},"5497558138880",[38,610,100],{"class":59},[38,612,613,616,618],{"class":40,"line":116},[38,614,615],{"class":90},"  \"incomingBytes\"",[38,617,94],{"class":59},[38,619,620],{"class":48},"62914560\n",[38,622,623],{"class":40,"line":127},[38,624,130],{"class":59},[11,626,627,628,247],{},"Caps are set when the credential is provisioned for you as part of a plan. Self-provisioned\ncredentials are created with the default plan limits. See ",[341,629,631],{"href":630},"\u002Fdocs\u002Flimits","Limits",[633,634,635],"style",{},"html pre.shiki code .sAxfE, html code.shiki .sAxfE{--shiki-default:#FFA657;--shiki-dark:#FFA657}html pre.shiki code .sEQcL, html code.shiki .sEQcL{--shiki-default:#79C0FF;--shiki-dark:#79C0FF}html pre.shiki code .skZ57, html code.shiki .skZ57{--shiki-default:#A5D6FF;--shiki-dark:#A5D6FF}html pre.shiki code .sb7RM, html code.shiki .sb7RM{--shiki-default:#E6EDF3;--shiki-dark:#E6EDF3}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sV7Mv, html code.shiki .sV7Mv{--shiki-default:#7EE787;--shiki-dark:#7EE787}",{"title":33,"searchDepth":103,"depth":103,"links":637},[638,639,640,641,642],{"id":17,"depth":87,"text":18},{"id":287,"depth":87,"text":288},{"id":348,"depth":87,"text":349},{"id":491,"depth":87,"text":492},{"id":569,"depth":87,"text":570},"Provision, verify, and revoke the ed25519 credential that is both your API identity and your account.","md",{},true,"\u002Fdocs\u002Fapi\u002Fprovisioning","API reference",{"title":5,"description":643},"docs\u002Fapi\u002Fprovisioning","XQbQWgn7iOv_phw_P28iJ4u-38Y4_oOdqAesvBquZz4",[653,657,661,665,666,670,674,679,683,687,690,694],{"path":654,"title":655,"description":656,"section":648,"order":127,"badge":6},"\u002Fdocs\u002Fapi\u002Faccount","Account","GET \u002Faccount — stored, read, and written byte counters for your credential.",{"path":658,"title":659,"description":660,"section":648,"order":116,"badge":6},"\u002Fdocs\u002Fapi\u002Fobjects","Objects","Register, read, list, and delete objects — ordered lists of slab segments with encrypted keys and opaque metadata.",{"path":662,"title":663,"description":664,"section":648,"order":87,"badge":6},"\u002Fdocs\u002Fapi\u002Fplacement","Placement","POST \u002Fprepare-write — get the providers, contracts, and access tokens for writing a slab's shards.",{"path":647,"title":5,"description":643,"section":648,"order":41,"badge":6},{"path":667,"title":668,"description":669,"section":648,"order":103,"badge":6},"\u002Fdocs\u002Fapi\u002Fslabs","Slabs","Register, read, list, unpin, and prune erasure-coded slabs — the layer that records which provider holds which shard.",{"path":671,"title":344,"description":672,"section":673,"order":87,"badge":6},"\u002Fdocs\u002Fauthentication","Every request is signed with ed25519 over a blake2b hash of the method, host, path, expiry, and body. Here is the exact construction, with working code.","Guides",{"path":675,"title":676,"description":677,"section":678,"order":87,"badge":6},"\u002Fdocs\u002Fconcepts","Concepts & data model","Sectors, shards, slabs, objects, and accounts — what each one is, why the model has no filenames, and what that means for your integration.","Introduction",{"path":680,"title":211,"description":681,"section":682,"order":41,"badge":6},"\u002Fdocs\u002Ferrors","Status codes, the two different error body formats, and the one case where a failure arrives with a 200.","Reference",{"path":684,"title":685,"description":686,"section":678,"order":41,"badge":6},"\u002Fdocs","Overview","Tessera is an HTTP API for storing encrypted, erasure-coded objects across independent storage providers. This is the reference for it.",{"path":630,"title":688,"description":689,"section":682,"order":87,"badge":6},"Limits & quotas","Rate limits, storage caps, geometry constraints, and the size and encoding limits that apply to every request.",{"path":691,"title":692,"description":693,"section":673,"order":41,"badge":6},"\u002Fdocs\u002Fquickstart","Quickstart","Provision a credential, upload an object across 15 providers, and read it back. Fifteen minutes, one file of code.",{"path":695,"title":696,"description":697,"section":673,"order":103,"badge":6},"\u002Fdocs\u002Frecovery","Recovery without Tessera","How to retrieve your data if Tessera is unavailable, unwilling, or permanently gone — and what you need to keep on hand for that to work.",1786190913538]