[{"data":1,"prerenderedAt":618},["ShallowReactive",2],{"navigation_docs":3,"-api-authentication":183,"-api-authentication-surround":613},[4,25,60,81,153,168],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":6},"Getting started",false,"\u002Fgetting-started","1.getting-started",[10,15,20],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Quickstart","\u002Fgetting-started\u002Fquickstart","1.getting-started\u002F2.quickstart","i-lucide-zap",{"title":21,"path":22,"stem":23,"icon":24},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F3.installation","i-lucide-server",{"title":26,"icon":6,"path":27,"stem":28,"children":29,"page":6},"Concepts","\u002Fconcepts","2.concepts",[30,35,40,45,50,55],{"title":31,"path":32,"stem":33,"icon":34},"How AML works","\u002Fconcepts\u002Fhow-aml-works","2.concepts\u002F1.how-aml-works","i-lucide-book-open",{"title":36,"path":37,"stem":38,"icon":39},"Events and decisions","\u002Fconcepts\u002Fevents-and-decisions","2.concepts\u002F2.events-and-decisions","i-lucide-activity",{"title":41,"path":42,"stem":43,"icon":44},"Rules","\u002Fconcepts\u002Frules","2.concepts\u002F3.rules","i-lucide-scale",{"title":46,"path":47,"stem":48,"icon":49},"Alerts, cases and reporting","\u002Fconcepts\u002Falerts-cases-reporting","2.concepts\u002F4.alerts-cases-reporting","i-lucide-folder-search",{"title":51,"path":52,"stem":53,"icon":54},"Entities and the graph","\u002Fconcepts\u002Fentities-and-graph","2.concepts\u002F5.entities-and-graph","i-lucide-network",{"title":56,"path":57,"stem":58,"icon":59},"Audit log","\u002Fconcepts\u002Faudit-log","2.concepts\u002F6.audit-log","i-lucide-scroll-text",{"title":61,"icon":6,"path":62,"stem":63,"children":64,"page":6},"Guides","\u002Fguides","3.guides",[65,70,75],{"title":66,"path":67,"stem":68,"icon":69},"Guides by role","\u002Fguides\u002Fby-role","3.guides\u002F1.by-role","i-lucide-users",{"title":71,"path":72,"stem":73,"icon":74},"Integration plan","\u002Fguides\u002Fintegration-plan","3.guides\u002F2.integration-plan","i-lucide-list-checks",{"title":76,"path":77,"stem":78,"icon":79,"badge":80},"Connecting a rail","\u002Fguides\u002Fconnecting-a-rail","3.guides\u002F3.connecting-a-rail","i-lucide-plug","Coming soon",{"title":82,"icon":6,"path":83,"stem":84,"children":85,"page":6},"API reference","\u002Fapi","4.api",[86,91,96,101,106,111,116,121,126,129,134,139,144,149],{"title":87,"path":88,"stem":89,"icon":90},"Authentication","\u002Fapi\u002Fauthentication","4.api\u002F01.authentication","i-lucide-key-round",{"title":92,"path":93,"stem":94,"icon":95},"Errors","\u002Fapi\u002Ferrors","4.api\u002F02.errors","i-lucide-circle-alert",{"title":97,"path":98,"stem":99,"icon":100},"Idempotency","\u002Fapi\u002Fidempotency","4.api\u002F03.idempotency","i-lucide-repeat",{"title":102,"path":103,"stem":104,"icon":105},"Health","\u002Fapi\u002Fhealth","4.api\u002F04.health","i-lucide-heart-pulse",{"title":107,"path":108,"stem":109,"icon":110},"Entities","\u002Fapi\u002Fentities","4.api\u002F05.entities","i-lucide-user-round",{"title":112,"path":113,"stem":114,"icon":115},"Events","\u002Fapi\u002Fevents","4.api\u002F06.events","i-lucide-send",{"title":117,"path":118,"stem":119,"icon":120},"Decisions","\u002Fapi\u002Fdecisions","4.api\u002F07.decisions","i-lucide-gavel",{"title":122,"path":123,"stem":124,"icon":125},"Alerts","\u002Fapi\u002Falerts","4.api\u002F08.alerts","i-lucide-bell",{"title":41,"path":127,"stem":128,"icon":44},"\u002Fapi\u002Frules","4.api\u002F09.rules",{"title":130,"path":131,"stem":132,"icon":133},"Screening","\u002Fapi\u002Fscreening","4.api\u002F10.screening","i-lucide-user-search",{"title":135,"path":136,"stem":137,"icon":138},"API keys","\u002Fapi\u002Fapi-keys","4.api\u002F11.api-keys","i-lucide-key",{"title":140,"path":141,"stem":142,"icon":143},"Overview","\u002Fapi\u002Foverview","4.api\u002F12.overview","i-lucide-layout-dashboard",{"title":145,"path":146,"stem":147,"icon":148,"badge":80},"Webhooks","\u002Fapi\u002Fwebhooks","4.api\u002F13.webhooks","i-lucide-webhook",{"title":80,"path":150,"stem":151,"icon":152,"badge":80},"\u002Fapi\u002Fcoming-soon","4.api\u002F14.coming-soon","i-lucide-clock",{"title":154,"icon":6,"path":155,"stem":156,"children":157,"page":6},"Security and licensing","\u002Fsecurity","5.security",[158,163],{"title":159,"path":160,"stem":161,"icon":162},"Data flows","\u002Fsecurity\u002Fdata-flows","5.security\u002F1.data-flows","i-lucide-shield-check",{"title":164,"path":165,"stem":166,"icon":167,"badge":80},"Licensing and metering","\u002Fsecurity\u002Flicensing","5.security\u002F2.licensing","i-lucide-file-badge",{"title":169,"icon":6,"path":170,"stem":171,"children":172,"page":6},"Reference","\u002Freference","6.reference",[173,178],{"title":174,"path":175,"stem":176,"icon":177},"Glossary","\u002Freference\u002Fglossary","6.reference\u002F1.glossary","i-lucide-book-a",{"title":179,"path":180,"stem":181,"icon":182},"FAQ","\u002Freference\u002Ffaq","6.reference\u002F2.faq","i-lucide-circle-help",{"id":184,"title":87,"body":185,"description":606,"extension":607,"links":608,"meta":609,"navigation":610,"path":88,"seo":611,"stem":89,"__hash__":612},"docs\u002F4.api\u002F01.authentication.md",{"type":186,"value":187,"toc":598},"minimark",[188,201,206,213,223,230,233,246,279,310,314,318,321,385,392,425,439,444,451,499,505,539,542,546,553,594],[189,190,191,192,196,197,200],"p",{},"The Sentinel API is JSON over HTTPS, versioned under ",[193,194,195],"code",{},"\u002Fv1",". The OpenAPI 3.1 file that ships with each release (",[193,198,199],{},"api\u002Fopenapi.yaml",") is the source of truth; these pages are written from it.",[202,203,205],"h2",{"id":204},"base-url","Base URL",[189,207,208,209,212],{},"Your install serves the API on your own network, so the base URL is whatever host you run it on. A local install listens on ",[193,210,211],{},"http:\u002F\u002Flocalhost:8080",".",[214,215,221],"pre",{"className":216,"code":218,"language":219,"meta":220},[217],"language-text","https:\u002F\u002Fsentinel.internal.example.com\u002Fv1\u002F...\n","text","",[193,222,218],{"__ignoreMap":220},[189,224,225,226,229],{},"The same server also serves the dashboard at ",[193,227,228],{},"\u002F",". The API doesn't need to be exposed to the public internet. Your payment services call it over your internal network.",[202,231,135],{"id":232},"api-keys",[189,234,235,236,238,239,245],{},"Send a key as a bearer token on every ",[193,237,195],{}," request. ",[240,241,242],"a",{"href":103},[193,243,244],{},"\u002Fhealthz"," is the only route that doesn't need one.",[214,247,251],{"className":248,"code":249,"language":250,"meta":220,"style":220},"language-http shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","POST \u002Fv1\u002Fevents?mode=sync HTTP\u002F1.1\nHost: sentinel.internal.example.com\nAuthorization: Bearer snt_live_...\nContent-Type: application\u002Fjson\n","http",[193,252,253,261,267,273],{"__ignoreMap":220},[254,255,258],"span",{"class":256,"line":257},"line",1,[254,259,260],{},"POST \u002Fv1\u002Fevents?mode=sync HTTP\u002F1.1\n",[254,262,264],{"class":256,"line":263},2,[254,265,266],{},"Host: sentinel.internal.example.com\n",[254,268,270],{"class":256,"line":269},3,[254,271,272],{},"Authorization: Bearer snt_live_...\n",[254,274,276],{"class":256,"line":275},4,[254,277,278],{},"Content-Type: application\u002Fjson\n",[280,281,282,290,293,296,299,302],"ul",{},[283,284,285,286,289],"li",{},"Keys start with ",[193,287,288],{},"snt_live_",". The rest is 32 random bytes, URL-safe base64.",[283,291,292],{},"Each key is shown once, when it's created. Only a SHA-256 hash is stored, so a lost key can't be recovered. Create a new one.",[283,294,295],{},"Each key belongs to one organisation, and every request is scoped to it. You only ever see records in your own organisation.",[283,297,298],{},"Keys are checked against your install's own database. Somu Labs never sees them.",[283,300,301],{},"Revoking a key takes effect on the next request. Revoked keys stay listed for the audit trail.",[283,303,304,305,309],{},"The key making a request is its ",[306,307,308],"strong",{},"actor",". Notes, closure requests, approvals and rule changes record the key's ID, and four-eyes checks compare key IDs.",[311,312,313],"warning",{},"Every key can do everything in its organisation today, including creating and revoking other keys. There are no scopes and no test keys yet. Give each service or person their own key so you can revoke one without breaking the rest.",[202,315,317],{"id":316},"creating-keys","Creating keys",[189,319,320],{},"There are three ways to get a key.",[322,323,324,340],"table",{},[325,326,327],"thead",{},[328,329,330,334,337],"tr",{},[331,332,333],"th",{},"Where",[331,335,336],{},"How",[331,338,339],{},"Use it for",[341,342,343,357,372],"tbody",{},[328,344,345,349,354],{},[346,347,348],"td",{},"Dashboard",[346,350,351],{},[306,352,353],{},"Developers → API keys → Create key",[346,355,356],{},"Day-to-day, once you can sign in",[328,358,359,362,369],{},[346,360,361],{},"API",[346,363,364],{},[240,365,366],{"href":136},[193,367,368],{},"POST \u002Fv1\u002Fkeys",[346,370,371],{},"Automation",[328,373,374,377,382],{},[346,375,376],{},"Command line",[346,378,379],{},[193,380,381],{},"sentinel-admin key create -org \u003Corg> -name \u003Cname>",[346,383,384],{},"Any time you have database access, including a fresh install",[189,386,387,388,391],{},"The command line tool reads ",[193,389,390],{},"SENTINEL_DATABASE_URL"," and prints the new key once:",[214,393,398],{"className":394,"code":395,"filename":396,"language":397,"meta":220,"style":220},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go run .\u002Fcmd\u002Fsentinel-admin key create -name dev\n","Terminal","bash",[193,399,400],{"__ignoreMap":220},[254,401,402,406,410,413,416,419,422],{"class":256,"line":257},[254,403,405],{"class":404},"sBMFI","go",[254,407,409],{"class":408},"sfazB"," run",[254,411,412],{"class":408}," .\u002Fcmd\u002Fsentinel-admin",[254,414,415],{"class":408}," key",[254,417,418],{"class":408}," create",[254,420,421],{"class":408}," -name",[254,423,424],{"class":408}," dev\n",[189,426,427,428,431,432,435,436,212],{},"In the container image it's ",[193,429,430],{},"\u002Fapp\u002Fsentinel-admin",". The ",[193,433,434],{},"-org"," flag defaults to ",[193,437,438],{},"default",[440,441,443],"h3",{"id":442},"the-first-key-on-a-fresh-install","The first key on a fresh install",[189,445,446,447,450],{},"A new install has no keys, so nothing can call the API or sign in to the dashboard. Either run ",[193,448,449],{},"sentinel-admin key create"," once, or set a bootstrap key before the first start:",[322,452,453,466],{},[325,454,455],{},[328,456,457,460,463],{},[331,458,459],{},"Variable",[331,461,462],{},"Default",[331,464,465],{},"Meaning",[341,467,468,485],{},[328,469,470,475,478],{},[346,471,472],{},[193,473,474],{},"SENTINEL_BOOTSTRAP_API_KEY",[346,476,477],{},"unset",[346,479,480,481,484],{},"Stored as the organisation's first key, named ",[193,482,483],{},"bootstrap",", but only while the organisation has no active key",[328,486,487,492,496],{},[346,488,489],{},[193,490,491],{},"SENTINEL_BOOTSTRAP_ORG",[346,493,494],{},[193,495,438],{},[346,497,498],{},"The organisation the bootstrap key belongs to",[189,500,501,502,504],{},"The value must start with ",[193,503,288],{}," and be at least 40 characters long. One way to make one:",[214,506,508],{"className":394,"code":507,"filename":396,"language":397,"meta":220,"style":220},"echo snt_live_$(openssl rand -hex 24)\n",[193,509,510],{"__ignoreMap":220},[254,511,512,516,519,523,526,529,532,536],{"class":256,"line":257},[254,513,515],{"class":514},"s2Zo4","echo",[254,517,518],{"class":408}," snt_live_",[254,520,522],{"class":521},"sMK4o","$(",[254,524,525],{"class":404},"openssl",[254,527,528],{"class":408}," rand",[254,530,531],{"class":408}," -hex",[254,533,535],{"class":534},"sbssI"," 24",[254,537,538],{"class":521},")\n",[189,540,541],{},"Once the organisation has an active key, the setting does nothing, so leaving it in place is harmless and a revoked bootstrap key is never brought back. Still, create your own keys, revoke the bootstrap one, and remove the variable.",[202,543,545],{"id":544},"failed-authentication","Failed authentication",[189,547,548,549,552],{},"A missing, invalid or revoked key returns ",[193,550,551],{},"401",":",[214,554,559],{"className":555,"code":556,"filename":557,"language":558,"meta":220,"style":220},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"error\": \"missing or invalid API key\"\n}\n","Response · 401","json",[193,560,561,566,589],{"__ignoreMap":220},[254,562,563],{"class":256,"line":257},[254,564,565],{"class":521},"{\n",[254,567,568,571,575,578,580,583,586],{"class":256,"line":263},[254,569,570],{"class":521},"  \"",[254,572,574],{"class":573},"spNyl","error",[254,576,577],{"class":521},"\"",[254,579,552],{"class":521},[254,581,582],{"class":521}," \"",[254,584,585],{"class":408},"missing or invalid API key",[254,587,588],{"class":521},"\"\n",[254,590,591],{"class":256,"line":269},[254,592,593],{"class":521},"}\n",[595,596,597],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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 .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}",{"title":220,"searchDepth":263,"depth":263,"links":599},[600,601,602,605],{"id":204,"depth":263,"text":205},{"id":232,"depth":263,"text":135},{"id":316,"depth":263,"text":317,"children":603},[604],{"id":442,"depth":269,"text":443},{"id":544,"depth":263,"text":545},"Base URL, API keys, and how to get the first key on a new install.","md",null,{},{"icon":90},{"title":87,"description":606},"mowrFM13tdlbH2sT_pD69TJUkR6DUkNsS2G3v-qdK8o",[614,616],{"title":76,"path":77,"stem":78,"description":615,"icon":79,"badge":80,"children":-1},"Use a connector to bring events from a payment rail into Sentinel without writing integration code.",{"title":92,"path":93,"stem":94,"description":617,"icon":95,"children":-1},"Status codes and the error body the API returns.",1792169656545]