[{"data":1,"prerenderedAt":743},["ShallowReactive",2],{"docs:\u002Fdocs\u002Frecovery":3,"docs:nav":694},{"id":4,"title":5,"badge":6,"body":7,"description":686,"extension":687,"meta":688,"navigation":170,"order":143,"path":689,"section":690,"seo":691,"stem":692,"__hash__":693},"docs\u002Fdocs\u002Frecovery.md","Recovery without Tessera",null,{"type":8,"value":9,"toc":678},"minimark",[10,14,17,22,25,64,67,71,74,543,559,562,574,578,585,592,599,603,606,609,613,616,643,646,650,653,671,674],[11,12,13],"p",{},"Tessera is not in the data path. That is an architectural fact with a useful consequence: given the\nplacement record for an object, a client can retrieve and reconstruct it from providers with no\ninvolvement from us at all.",[11,15,16],{},"This page explains how to keep yourself in that position. We would rather you were able to leave\nthan dependent on us being solvent.",[18,19,21],"h2",{"id":20},"what-you-need","What you need",[11,23,24],{},"Three things, all of which you can obtain today through the API:",[26,27,28,41,54],"ol",{},[29,30,31,35,36,40],"li",{},[32,33,34],"strong",{},"The object record"," — ",[37,38,39],"code",{},"GET \u002Fobjects\u002F{key}",": the slab list with offsets and lengths, and the\nwrapped data key.",[29,42,43,35,46,49,50,53],{},[32,44,45],{},"The slab records",[37,47,48],{},"GET \u002Fslabs\u002F{id}"," for each referenced slab: ",[37,51,52],{},"minShards",", the encryption\nparameter, and for each shard its provider public key, network address, and sector root.",[29,55,56,59,60,63],{},[32,57,58],{},"Your key material"," — whatever unwraps ",[37,61,62],{},"encryptedDataKey",". This has always been yours and we\nhave never held it.",[11,65,66],{},"With those, retrieval is: connect to any 10 of the 15 providers named in the slab, request the\nsectors by root, verify each against its root, run Reed–Solomon reconstruction, concatenate the\nslab segments in order, decrypt.",[18,68,70],{"id":69},"exporting-your-placement-records","Exporting your placement records",[11,72,73],{},"There is no single-call export endpoint yet, so an export is a walk over two endpoints:",[75,76,81],"pre",{"className":77,"code":78,"language":79,"meta":80,"style":80},"language-ts shiki shiki-themes github-dark-default github-dark-default","async function exportPlacement() {\n  const manifest: Record\u003Cstring, unknown> = {}\n  const seenSlabs = new Set\u003Cstring>()\n\n  let after: string | undefined\n  for (;;) {\n    const qs = new URLSearchParams({ limit: '100', ...(after ? { after } : {}) })\n    const events = await call('GET', `\u002Fobjects?${qs}`)\n    if (!events.length) break\n\n    for (const ev of events) {\n      if (ev.deleted) {\n        delete manifest[ev.key]\n        continue\n      }\n      manifest[ev.key] = ev.object\n      for (const s of ev.object.slabs) seenSlabs.add(s.id)\n    }\n    after = events[events.length - 1].updatedAt\n  }\n\n  const slabs: Record\u003Cstring, unknown> = {}\n  for (const id of seenSlabs) {\n    slabs[id] = await call('GET', `\u002Fslabs\u002F${id}`)\n  }\n\n  return { exportedAt: new Date().toISOString(), objects: manifest, slabs }\n}\n","ts","",[37,82,83,103,141,165,172,192,201,243,279,303,308,328,337,346,352,358,369,393,399,421,427,432,458,475,503,508,513,537],{"__ignoreMap":80},[84,85,88,92,95,99],"span",{"class":86,"line":87},"line",1,[84,89,91],{"class":90},"srH4v","async",[84,93,94],{"class":90}," function",[84,96,98],{"class":97},"sYGIp"," exportPlacement",[84,100,102],{"class":101},"sb7RM","() {\n",[84,104,106,109,113,116,120,123,126,129,132,135,138],{"class":86,"line":105},2,[84,107,108],{"class":90},"  const",[84,110,112],{"class":111},"sEQcL"," manifest",[84,114,115],{"class":90},":",[84,117,119],{"class":118},"sAxfE"," Record",[84,121,122],{"class":101},"\u003C",[84,124,125],{"class":111},"string",[84,127,128],{"class":101},", ",[84,130,131],{"class":111},"unknown",[84,133,134],{"class":101},"> ",[84,136,137],{"class":90},"=",[84,139,140],{"class":101}," {}\n",[84,142,144,146,149,152,155,158,160,162],{"class":86,"line":143},3,[84,145,108],{"class":90},[84,147,148],{"class":111}," seenSlabs",[84,150,151],{"class":90}," =",[84,153,154],{"class":90}," new",[84,156,157],{"class":97}," Set",[84,159,122],{"class":101},[84,161,125],{"class":111},[84,163,164],{"class":101},">()\n",[84,166,168],{"class":86,"line":167},4,[84,169,171],{"emptyLinePlaceholder":170},true,"\n",[84,173,175,178,181,183,186,189],{"class":86,"line":174},5,[84,176,177],{"class":90},"  let",[84,179,180],{"class":101}," after",[84,182,115],{"class":90},[84,184,185],{"class":111}," string",[84,187,188],{"class":90}," |",[84,190,191],{"class":111}," undefined\n",[84,193,195,198],{"class":86,"line":194},6,[84,196,197],{"class":90},"  for",[84,199,200],{"class":101}," (;;) {\n",[84,202,204,207,210,212,214,217,220,224,226,229,232,235,238,240],{"class":86,"line":203},7,[84,205,206],{"class":90},"    const",[84,208,209],{"class":111}," qs",[84,211,151],{"class":90},[84,213,154],{"class":90},[84,215,216],{"class":97}," URLSearchParams",[84,218,219],{"class":101},"({ limit: ",[84,221,223],{"class":222},"skZ57","'100'",[84,225,128],{"class":101},[84,227,228],{"class":90},"...",[84,230,231],{"class":101},"(after ",[84,233,234],{"class":90},"?",[84,236,237],{"class":101}," { after } ",[84,239,115],{"class":90},[84,241,242],{"class":101}," {}) })\n",[84,244,246,248,251,253,256,259,262,265,267,270,273,276],{"class":86,"line":245},8,[84,247,206],{"class":90},[84,249,250],{"class":111}," events",[84,252,151],{"class":90},[84,254,255],{"class":90}," await",[84,257,258],{"class":97}," call",[84,260,261],{"class":101},"(",[84,263,264],{"class":222},"'GET'",[84,266,128],{"class":101},[84,268,269],{"class":222},"`\u002Fobjects?${",[84,271,272],{"class":101},"qs",[84,274,275],{"class":222},"}`",[84,277,278],{"class":101},")\n",[84,280,282,285,288,291,294,297,300],{"class":86,"line":281},9,[84,283,284],{"class":90},"    if",[84,286,287],{"class":101}," (",[84,289,290],{"class":90},"!",[84,292,293],{"class":101},"events.",[84,295,296],{"class":111},"length",[84,298,299],{"class":101},") ",[84,301,302],{"class":90},"break\n",[84,304,306],{"class":86,"line":305},10,[84,307,171],{"emptyLinePlaceholder":170},[84,309,311,314,316,319,322,325],{"class":86,"line":310},11,[84,312,313],{"class":90},"    for",[84,315,287],{"class":101},[84,317,318],{"class":90},"const",[84,320,321],{"class":111}," ev",[84,323,324],{"class":90}," of",[84,326,327],{"class":101}," events) {\n",[84,329,331,334],{"class":86,"line":330},12,[84,332,333],{"class":90},"      if",[84,335,336],{"class":101}," (ev.deleted) {\n",[84,338,340,343],{"class":86,"line":339},13,[84,341,342],{"class":90},"        delete",[84,344,345],{"class":101}," manifest[ev.key]\n",[84,347,349],{"class":86,"line":348},14,[84,350,351],{"class":90},"        continue\n",[84,353,355],{"class":86,"line":354},15,[84,356,357],{"class":101},"      }\n",[84,359,361,364,366],{"class":86,"line":360},16,[84,362,363],{"class":101},"      manifest[ev.key] ",[84,365,137],{"class":90},[84,367,368],{"class":101}," ev.object\n",[84,370,372,375,377,379,382,384,387,390],{"class":86,"line":371},17,[84,373,374],{"class":90},"      for",[84,376,287],{"class":101},[84,378,318],{"class":90},[84,380,381],{"class":111}," s",[84,383,324],{"class":90},[84,385,386],{"class":101}," ev.object.slabs) seenSlabs.",[84,388,389],{"class":97},"add",[84,391,392],{"class":101},"(s.id)\n",[84,394,396],{"class":86,"line":395},18,[84,397,398],{"class":101},"    }\n",[84,400,402,405,407,410,412,415,418],{"class":86,"line":401},19,[84,403,404],{"class":101},"    after ",[84,406,137],{"class":90},[84,408,409],{"class":101}," events[events.",[84,411,296],{"class":111},[84,413,414],{"class":90}," -",[84,416,417],{"class":111}," 1",[84,419,420],{"class":101},"].updatedAt\n",[84,422,424],{"class":86,"line":423},20,[84,425,426],{"class":101},"  }\n",[84,428,430],{"class":86,"line":429},21,[84,431,171],{"emptyLinePlaceholder":170},[84,433,435,437,440,442,444,446,448,450,452,454,456],{"class":86,"line":434},22,[84,436,108],{"class":90},[84,438,439],{"class":111}," slabs",[84,441,115],{"class":90},[84,443,119],{"class":118},[84,445,122],{"class":101},[84,447,125],{"class":111},[84,449,128],{"class":101},[84,451,131],{"class":111},[84,453,134],{"class":101},[84,455,137],{"class":90},[84,457,140],{"class":101},[84,459,461,463,465,467,470,472],{"class":86,"line":460},23,[84,462,197],{"class":90},[84,464,287],{"class":101},[84,466,318],{"class":90},[84,468,469],{"class":111}," id",[84,471,324],{"class":90},[84,473,474],{"class":101}," seenSlabs) {\n",[84,476,478,481,483,485,487,489,491,493,496,499,501],{"class":86,"line":477},24,[84,479,480],{"class":101},"    slabs[id] ",[84,482,137],{"class":90},[84,484,255],{"class":90},[84,486,258],{"class":97},[84,488,261],{"class":101},[84,490,264],{"class":222},[84,492,128],{"class":101},[84,494,495],{"class":222},"`\u002Fslabs\u002F${",[84,497,498],{"class":101},"id",[84,500,275],{"class":222},[84,502,278],{"class":101},[84,504,506],{"class":86,"line":505},25,[84,507,426],{"class":101},[84,509,511],{"class":86,"line":510},26,[84,512,171],{"emptyLinePlaceholder":170},[84,514,516,519,522,525,528,531,534],{"class":86,"line":515},27,[84,517,518],{"class":90},"  return",[84,520,521],{"class":101}," { exportedAt: ",[84,523,524],{"class":90},"new",[84,526,527],{"class":97}," Date",[84,529,530],{"class":101},"().",[84,532,533],{"class":97},"toISOString",[84,535,536],{"class":101},"(), objects: manifest, slabs }\n",[84,538,540],{"class":86,"line":539},28,[84,541,542],{"class":101},"}\n",[544,545,548],"app-callout",{"title":546,"tone":547},"Mind the rate limit on a large export","warn",[11,549,550,551,554,555,558],{},"30 requests per minute per credential, and a full export is one request per slab. For a large\naccount, run the export as a background job with backoff and checkpointing rather than a single\npass. Respect ",[37,552,553],{},"Retry-After"," on ",[37,556,557],{},"429",".",[11,560,561],{},"Store the result with your own backups — the same discipline you would apply to a database dump. It\nis small, it compresses well, and it contains no plaintext.",[544,563,566],{"title":564,"tone":565},"Export after writes, not on a timer alone","note",[11,567,568,569,573],{},"Placement changes when repair moves a shard to a new provider, so an old export can name providers\nthat no longer hold your shards. Reconstruction still succeeds as long as 10 of the named providers\nare current, but the safer pattern is to export after each batch of writes ",[570,571,572],"em",{},"and"," refresh\nperiodically. The provider addresses are the part that goes stale, not the roots.",[18,575,577],{"id":576},"the-prepaid-window","The prepaid window",[11,579,580,581,584],{},"Storage contracts are funded roughly ",[32,582,583],{},"12 weeks"," ahead of need. We deliberately overpay: it costs\nus margin and buys a property we consider worth more than the margin.",[11,586,587,588,591],{},"If Tessera stopped operating tomorrow and nobody renewed anything, your shards would remain stored\nand retrievable for ",[32,589,590],{},"at least 60 days",", because the providers have already been paid to hold them.\nNothing needs to happen for that to be true, and nobody needs to be reachable.",[544,593,596],{"title":594,"tone":595},"Why this is a floor and not a promise","good",[11,597,598],{},"60 days is the conservative published figure, not a service commitment we might reinterpret later.\nIt follows from contract terms already funded on the network. A promise depends on the promiser\nexisting; this does not.",[18,600,602],{"id":601},"reconstruction-without-our-client","Reconstruction without our client",[11,604,605],{},"Nothing about retrieval is proprietary. Providers speak an open protocol, sectors are addressed by\nMerkle root, and the erasure coding is standard Reed–Solomon over GF(2^8). A competent engineer with\nyour export and the protocol specification can rebuild your data using open-source libraries and no\ncooperation from us.",[11,607,608],{},"That is the point. Our moat is provider curation, contract management, and repair — the work that is\ntedious to do well. It is not, and should not be, control over your ability to read your own data.",[18,610,612],{"id":611},"what-you-would-lose","What you would lose",[11,614,615],{},"To be balanced about it, if we vanished you would lose real things:",[617,618,619,625,631,637],"ul",{},[29,620,621,624],{},[32,622,623],{},"Repair."," Shard loss would stop being fixed, so redundancy would decay from 15 toward 10 and\neventually below it. This is the clock that matters, and it is slower than the payment clock.",[29,626,627,630],{},[32,628,629],{},"Renewal."," Contracts would expire at the end of their funded term, which is where the 60-day\nfloor comes from.",[29,632,633,636],{},[32,634,635],{},"Provider curation."," No further vetting, no replacement of underperforming providers.",[29,638,639,642],{},[32,640,641],{},"The convenient lookup path."," Your export becomes the only copy of your placement record, which\nis exactly why you should hold one.",[11,644,645],{},"Your data would be recoverable, not maintained. The correct action in that scenario is to retrieve\neverything and re-store it elsewhere, promptly — not to treat the window as indefinite.",[18,647,649],{"id":648},"a-recovery-drill-worth-running","A recovery drill worth running",[11,651,652],{},"Do this once, on purpose, before you need to:",[26,654,655,658,665,668],{},[29,656,657],{},"Export placement records for a handful of objects.",[29,659,660,661,664],{},"Write a retrieval script that uses ",[32,662,663],{},"only"," the export — no calls to our API at all.",[29,666,667],{},"Confirm it reconstructs and decrypts correctly.",[29,669,670],{},"Store the script alongside the export, with its dependencies pinned.",[11,672,673],{},"An untested recovery path is a hypothesis. Testing it takes an afternoon and converts your\ndependency on us from structural to merely convenient.",[675,676,677],"style",{},"html pre.shiki code .srH4v, html code.shiki .srH4v{--shiki-default:#FF7B72;--shiki-dark:#FF7B72}html pre.shiki code .sYGIp, html code.shiki .sYGIp{--shiki-default:#D2A8FF;--shiki-dark:#D2A8FF}html pre.shiki code .sb7RM, html code.shiki .sb7RM{--shiki-default:#E6EDF3;--shiki-dark:#E6EDF3}html pre.shiki code .sEQcL, html code.shiki .sEQcL{--shiki-default:#79C0FF;--shiki-dark:#79C0FF}html pre.shiki code .sAxfE, html code.shiki .sAxfE{--shiki-default:#FFA657;--shiki-dark:#FFA657}html pre.shiki code .skZ57, html code.shiki .skZ57{--shiki-default:#A5D6FF;--shiki-dark:#A5D6FF}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);}",{"title":80,"searchDepth":143,"depth":143,"links":679},[680,681,682,683,684,685],{"id":20,"depth":105,"text":21},{"id":69,"depth":105,"text":70},{"id":576,"depth":105,"text":577},{"id":601,"depth":105,"text":602},{"id":611,"depth":105,"text":612},{"id":648,"depth":105,"text":649},"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.","md",{},"\u002Fdocs\u002Frecovery","Guides",{"title":5,"description":686},"docs\u002Frecovery","QgEjUdahKxBetebEFdqZ-GEML4bSDQt3BX0XrVnqZoU",[695,700,704,708,712,716,720,725,730,734,738,742],{"path":696,"title":697,"description":698,"section":699,"order":174,"badge":6},"\u002Fdocs\u002Fapi\u002Faccount","Account","GET \u002Faccount — stored, read, and written byte counters for your credential.","API reference",{"path":701,"title":702,"description":703,"section":699,"order":167,"badge":6},"\u002Fdocs\u002Fapi\u002Fobjects","Objects","Register, read, list, and delete objects — ordered lists of slab segments with encrypted keys and opaque metadata.",{"path":705,"title":706,"description":707,"section":699,"order":105,"badge":6},"\u002Fdocs\u002Fapi\u002Fplacement","Placement","POST \u002Fprepare-write — get the providers, contracts, and access tokens for writing a slab's shards.",{"path":709,"title":710,"description":711,"section":699,"order":87,"badge":6},"\u002Fdocs\u002Fapi\u002Fprovisioning","Credentials","Provision, verify, and revoke the ed25519 credential that is both your API identity and your account.",{"path":713,"title":714,"description":715,"section":699,"order":143,"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":717,"title":718,"description":719,"section":690,"order":105,"badge":6},"\u002Fdocs\u002Fauthentication","Authentication","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.",{"path":721,"title":722,"description":723,"section":724,"order":105,"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":726,"title":727,"description":728,"section":729,"order":87,"badge":6},"\u002Fdocs\u002Ferrors","Errors","Status codes, the two different error body formats, and the one case where a failure arrives with a 200.","Reference",{"path":731,"title":732,"description":733,"section":724,"order":87,"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":735,"title":736,"description":737,"section":729,"order":105,"badge":6},"\u002Fdocs\u002Flimits","Limits & quotas","Rate limits, storage caps, geometry constraints, and the size and encoding limits that apply to every request.",{"path":739,"title":740,"description":741,"section":690,"order":87,"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":689,"title":5,"description":686,"section":690,"order":143,"badge":6},1786190914129]