[{"data":1,"prerenderedAt":10},["ShallowReactive",2],{"public:public\u002Fcontent\u002Fdocs\u002Fapi":3},{"slug":4,"title":5,"description":6,"draft":7,"updated":8,"html":9},"api","API tokens","Read-only access to runs, coverage, reports and evidence over \u002Fapi\u002Fv1 for CI pipelines and compliance tools.",false,null,"\u003Ch1>API tokens and \u002Fapi\u002Fv1\u003C\u002Fh1>\n\u003Cp>API tokens give scripts read-only access to one organisation: gate a deploy on the last restore test, pull coverage into a dashboard, or fetch evidence for an audit. A token can never change anything: there are no write routes for tokens, and the app API refuses them.\u003C\u002Fp>\n\u003Ch2>1. Create a token\u003C\u002Fh2>\n\u003Cp>\u003Cstrong>Organisation → API tokens\u003C\u002Fstrong> (owners and admins). Pick a name, the scopes and an expiry, then copy the token: it is shown once and stored only as a SHA-256 hash. The list shows its first characters, scopes and when it was last used. Revoking takes effect on the next request.\u003C\u002Fp>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Scope\u003C\u002Fth>\n\u003Cth>Routes\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>\u003Ccode>runs:read\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>GET \u002Fapi\u002Fv1\u002Fruns?target_id=…\u003C\u002Fcode>, \u003Ccode>GET \u002Fapi\u002Fv1\u002Fruns\u002F{run_id}\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>coverage:read\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>GET \u002Fapi\u002Fv1\u002Ftargets\u003C\u002Fcode>, \u003Ccode>GET \u002Fapi\u002Fv1\u002Ftargets\u002F{target_id}\u002Fcoverage\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>reports:read\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>GET \u002Fapi\u002Fv1\u002Fruns\u002F{run_id}\u002Freport.pdf\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>evidence:read\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>GET \u002Fapi\u002Fv1\u002Fruns\u002F{run_id}\u002Fverification\u003C\u002Fcode>, \u003Ccode>GET \u002Fapi\u002Fv1\u002Fevidence\u002F{period}\u003C\u002Fcode>, \u003Ccode>GET \u002Fapi\u002Fv1\u002Fevidence\u002F{period}\u002Fdownload\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Cp>Give each pipeline its own token with the fewest scopes it needs.\u003C\u002Fp>\n\u003Ch2>2. Call the API\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-sh\">curl -sf -H &quot;Authorization: Bearer $VERESTORE_TOKEN&quot; \\\n  https:\u002F\u002Fapp.verestore.dev\u002Fapi\u002Fv1\u002Ftargets\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cul>\n\u003Cli>\u003Ccode>GET \u002Fapi\u002Fv1\u002Ftargets\u003C\u002Fcode>: every target with its last run and coverage sentence.\u003C\u002Fli>\n\u003Cli>\u003Ccode>GET \u002Fapi\u002Fv1\u002Fruns?target_id=tgt_…&amp;limit=25&amp;cursor=…\u003C\u002Fcode>: a target&#39;s runs, newest first (\u003Ccode>items\u003C\u002Fcode>, \u003Ccode>nextCursor\u003C\u002Fcode>).\u003C\u002Fli>\n\u003Cli>\u003Ccode>GET \u002Fapi\u002Fv1\u002Fruns\u002F{run_id}\u003C\u002Fcode>: status, verdict, timings, backup identity, checks and countersignature state. The raw result is not included, and no row data ever is.\u003C\u002Fli>\n\u003Cli>\u003Ccode>GET \u002Fapi\u002Fv1\u002Fruns\u002F{run_id}\u002Fverification\u003C\u002Fcode>: the verification bundle to check offline or at \u003Ca href=\"mailto:support@verestore.dev?subject=Verestore%20launch\">\u002Fverify\u003C\u002Fa>.\u003C\u002Fli>\n\u003Cli>\u003Ccode>GET \u002Fapi\u002Fv1\u002Fevidence\u002F2026-Q4\u003C\u002Fcode> (or \u003Ccode>2026-11\u003C\u002Fcode>, optionally \u003Ccode>?target_id=\u003C\u002Fcode>): the evidence pack for a quarter or month, built on demand; \u003Ccode>…\u002Fdownload\u003C\u002Fcode> returns the ZIP with its SHA-256 in \u003Ccode>X-Content-SHA256\u003C\u002Fcode>.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Gate a deploy on the last test:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-sh\">status=$(curl -sf -H &quot;Authorization: Bearer $VERESTORE_TOKEN&quot; \\\n  &quot;https:\u002F\u002Fapp.verestore.dev\u002Fapi\u002Fv1\u002Fruns?target_id=$TARGET_ID&amp;limit=1&quot; | jq -r &#39;.items[0].status&#39;)\n[ &quot;$status&quot; = passed ] || { echo &quot;last restore test: $status&quot;; exit 1; }\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2>3. Errors and limits\u003C\u002Fh2>\n\u003Cp>Errors are \u003Ccode>application\u002Fproblem+json\u003C\u002Fcode>:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Ccode>401\u003C\u002Fcode>: missing, malformed, unknown, expired or revoked token.\u003C\u002Fli>\n\u003Cli>\u003Ccode>403\u003C\u002Fcode>: the token lacks the route&#39;s scope.\u003C\u002Fli>\n\u003Cli>\u003Ccode>404\u003C\u002Fcode>: no such resource in the token&#39;s organisation (another organisation&#39;s IDs look the same as missing ones).\u003C\u002Fli>\n\u003Cli>\u003Ccode>429\u003C\u002Fcode>: more than 120 requests a minute from one address; wait for \u003Ccode>Retry-After\u003C\u002Fcode>.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Signed-in members can call the same routes from the browser session; organisation-wide lists then take \u003Ccode>?org_id=org_…\u003C\u002Fcode>.\u003C\u002Fp>\n",1794290783587]