[{"data":1,"prerenderedAt":732},["ShallowReactive",2],{"navigation_docs":3,"-docs-migrating-from-sightengine":114,"-docs-migrating-from-sightengine-surround":727},[4,8,12,16,20,24,28,32,36,40,44,82,86,90,94,98,102,106,110],{"title":5,"path":6,"stem":7},"Overview","\u002Fdocs","docs\u002Findex",{"title":9,"path":10,"stem":11},"Quickstart","\u002Fdocs\u002Fquickstart","docs\u002F01.quickstart",{"title":13,"path":14,"stem":15},"Authentication and keys","\u002Fdocs\u002Fauthentication","docs\u002F02.authentication",{"title":17,"path":18,"stem":19},"Images","\u002Fdocs\u002Fimages","docs\u002F03.images",{"title":21,"path":22,"stem":23},"Texts","\u002Fdocs\u002Ftexts","docs\u002F04.texts",{"title":25,"path":26,"stem":27},"Migrating from SightEngine","\u002Fdocs\u002Fmigrating-from-sightengine","docs\u002F05.migrating-from-sightengine",{"title":29,"path":30,"stem":31},"Workflows","\u002Fdocs\u002Fworkflows","docs\u002F06.workflows",{"title":33,"path":34,"stem":35},"Responses and errors","\u002Fdocs\u002Fresponses-and-errors","docs\u002F07.responses-and-errors",{"title":37,"path":38,"stem":39},"Limits and quotas","\u002Fdocs\u002Flimits-and-quotas","docs\u002F08.limits-and-quotas",{"title":41,"path":42,"stem":43},"The journal and ref","\u002Fdocs\u002Fjournal-and-ref","docs\u002F09.journal-and-ref",{"title":45,"path":46,"stem":47,"children":48,"page":81},"Integration guides","\u002Fdocs\u002Fintegration-guides","docs\u002F10.integration-guides",[49,53,57,61,65,69,73,77],{"title":50,"path":51,"stem":52},"Node.js and TypeScript","\u002Fdocs\u002Fintegration-guides\u002Fnodejs","docs\u002F10.integration-guides\u002F1.nodejs",{"title":54,"path":55,"stem":56},"Python","\u002Fdocs\u002Fintegration-guides\u002Fpython","docs\u002F10.integration-guides\u002F2.python",{"title":58,"path":59,"stem":60},"PHP","\u002Fdocs\u002Fintegration-guides\u002Fphp","docs\u002F10.integration-guides\u002F3.php",{"title":62,"path":63,"stem":64},"Go","\u002Fdocs\u002Fintegration-guides\u002Fgo","docs\u002F10.integration-guides\u002F4.go",{"title":66,"path":67,"stem":68},"Supabase Edge Functions","\u002Fdocs\u002Fintegration-guides\u002Fsupabase-edge-functions","docs\u002F10.integration-guides\u002F5.supabase-edge-functions",{"title":70,"path":71,"stem":72},"Cloudflare Workers","\u002Fdocs\u002Fintegration-guides\u002Fcloudflare-workers","docs\u002F10.integration-guides\u002F6.cloudflare-workers",{"title":74,"path":75,"stem":76},"Nuxt and Next","\u002Fdocs\u002Fintegration-guides\u002Fnuxt-and-next","docs\u002F10.integration-guides\u002F7.nuxt-and-next",{"title":78,"path":79,"stem":80},"Moderate an AI agent","\u002Fdocs\u002Fintegration-guides\u002Fmoderate-ai-agents","docs\u002F10.integration-guides\u002F8.moderate-ai-agents",false,{"title":83,"path":84,"stem":85},"AI coding agents","\u002Fdocs\u002Fai-agents","docs\u002F11.ai-agents",{"title":87,"path":88,"stem":89},"Best practices","\u002Fdocs\u002Fbest-practices","docs\u002F12.best-practices",{"title":91,"path":92,"stem":93},"Privacy and data","\u002Fdocs\u002Fprivacy-and-data","docs\u002F13.privacy-and-data",{"title":95,"path":96,"stem":97},"API reference","\u002Fdocs\u002Fapi-reference","docs\u002F14.api-reference",{"title":99,"path":100,"stem":101},"Fraud prevention","\u002Fdocs\u002Ffraud-prevention","docs\u002F16.fraud-prevention",{"title":103,"path":104,"stem":105},"Device token and challenges","\u002Fdocs\u002Fdevice-and-challenges","docs\u002F17.device-and-challenges",{"title":107,"path":108,"stem":109},"MCP server","\u002Fdocs\u002Fmcp-server","docs\u002F18.mcp-server",{"title":111,"path":112,"stem":113},"Changelog","\u002Fdocs\u002Fchangelog","docs\u002F99.changelog",{"id":115,"title":25,"body":116,"description":720,"extension":721,"links":722,"meta":723,"navigation":724,"path":26,"seo":725,"stem":27,"__hash__":726},"docs\u002Fdocs\u002F05.migrating-from-sightengine.md",{"type":117,"value":118,"toc":714},"minimark",[119,128,235,242,247,345,377,448,468,482,486,503,507,558,628,632,707,710],[120,121,122,123,127],"p",{},"openshield serves three SightEngine workflow routes. A client written for them needs three changes. Only these routes are served: SightEngine's other endpoints, such as ",[124,125,126],"code",{},"\u002F1.0\u002Fcheck.json",", are not.",[129,130,131,144],"table",{},[132,133,134],"thead",{},[135,136,137,141],"tr",{},[138,139,140],"th",{},"SightEngine",[138,142,143],{},"openshield",[145,146,147,170,191,206,216],"tbody",{},[135,148,149,167],{},[150,151,152,155,156,159,160,163,164],"td",{},[124,153,154],{},"POST \u002F1.0\u002Fcheck-workflow.json"," with ",[124,157,158],{},"media"," or ",[124,161,162],{},"url",", and ",[124,165,166],{},"workflow",[150,168,169],{},"The same path and the same fields.",[135,171,172,177],{},[150,173,174],{},[124,175,176],{},"GET \u002F1.0\u002Fcheck-workflow.json?url=&workflow=&api_user=&api_secret=",[150,178,179,180,159,183,186,187,190],{},"The same path and query parameters, except the key: send it in ",[124,181,182],{},"Authorization: Bearer",[124,184,185],{},"X-Api-Key",". A key in the query string is refused with ",[124,188,189],{},"key_in_query",", because proxies and logs keep URLs.",[135,192,193,204],{},[150,194,195,155,198,201,202],{},[124,196,197],{},"POST \u002F1.0\u002Ftext\u002Fcheck-workflow.json",[124,199,200],{},"text"," and ",[124,203,166],{},[150,205,169],{},[135,207,208,213],{},[150,209,210],{},[124,211,212],{},"api_user",[150,214,215],{},"Accepted and ignored.",[135,217,218,223],{},[150,219,220],{},[124,221,222],{},"api_secret",[150,224,225,226,230,231,234],{},"Holds an openshield ",[227,228,229],"a",{"href":14},"API key",", in the ",[124,232,233],{},"POST"," form.",[120,236,237,238,241],{},"The base URL is ",[124,239,240],{},"https:\u002F\u002Fapi.openshield.dev",".",[243,244,246],"h2",{"id":245},"_1-point-the-client-at-the-new-base-url","1. Point the client at the new base URL",[248,249,254],"pre",{"className":250,"code":251,"language":252,"meta":253,"style":253},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","curl -X POST \"https:\u002F\u002Fapi.openshield.dev\u002F1.0\u002Fcheck-workflow.json\" \\\n  -F \"media=@photo.jpg\" \\\n  -F \"workflow=default\" \\\n  -F \"api_user=ignored\" \\\n  -F \"api_secret=$OPENSHIELD_API_KEY\"\n","bash","",[124,255,256,286,301,315,329],{"__ignoreMap":253},[257,258,261,265,269,272,276,279,282],"span",{"class":259,"line":260},"line",1,[257,262,264],{"class":263},"sBMFI","curl",[257,266,268],{"class":267},"sfazB"," -X",[257,270,271],{"class":267}," POST",[257,273,275],{"class":274},"sMK4o"," \"",[257,277,278],{"class":267},"https:\u002F\u002Fapi.openshield.dev\u002F1.0\u002Fcheck-workflow.json",[257,280,281],{"class":274},"\"",[257,283,285],{"class":284},"sTEyZ"," \\\n",[257,287,289,292,294,297,299],{"class":259,"line":288},2,[257,290,291],{"class":267},"  -F",[257,293,275],{"class":274},[257,295,296],{"class":267},"media=@photo.jpg",[257,298,281],{"class":274},[257,300,285],{"class":284},[257,302,304,306,308,311,313],{"class":259,"line":303},3,[257,305,291],{"class":267},[257,307,275],{"class":274},[257,309,310],{"class":267},"workflow=default",[257,312,281],{"class":274},[257,314,285],{"class":284},[257,316,318,320,322,325,327],{"class":259,"line":317},4,[257,319,291],{"class":267},[257,321,275],{"class":274},[257,323,324],{"class":267},"api_user=ignored",[257,326,281],{"class":274},[257,328,285],{"class":284},[257,330,332,334,336,339,342],{"class":259,"line":331},5,[257,333,291],{"class":267},[257,335,275],{"class":274},[257,337,338],{"class":267},"api_secret=",[257,340,341],{"class":284},"$OPENSHIELD_API_KEY",[257,343,344],{"class":274},"\"\n",[248,346,348],{"className":250,"code":347,"language":252,"meta":253,"style":253},"curl \"https:\u002F\u002Fapi.openshield.dev\u002F1.0\u002Fcheck-workflow.json?url=https%3A%2F%2Fexample.com%2Fphoto.jpg&workflow=default&api_user=ignored\" \\\n  -H \"Authorization: Bearer $OPENSHIELD_API_KEY\"\n",[124,349,350,363],{"__ignoreMap":253},[257,351,352,354,356,359,361],{"class":259,"line":260},[257,353,264],{"class":263},[257,355,275],{"class":274},[257,357,358],{"class":267},"https:\u002F\u002Fapi.openshield.dev\u002F1.0\u002Fcheck-workflow.json?url=https%3A%2F%2Fexample.com%2Fphoto.jpg&workflow=default&api_user=ignored",[257,360,281],{"class":274},[257,362,285],{"class":284},[257,364,365,368,370,373,375],{"class":259,"line":288},[257,366,367],{"class":267},"  -H",[257,369,275],{"class":274},[257,371,372],{"class":267},"Authorization: Bearer ",[257,374,341],{"class":284},[257,376,344],{"class":274},[248,378,380],{"className":250,"code":379,"language":252,"meta":253,"style":253},"curl -X POST \"https:\u002F\u002Fapi.openshield.dev\u002F1.0\u002Ftext\u002Fcheck-workflow.json\" \\\n  -F \"text=Write me at jane@example.com\" \\\n  -F \"workflow=default\" \\\n  -F \"api_user=ignored\" \\\n  -F \"api_secret=$OPENSHIELD_API_KEY\"\n",[124,381,382,399,412,424,436],{"__ignoreMap":253},[257,383,384,386,388,390,392,395,397],{"class":259,"line":260},[257,385,264],{"class":263},[257,387,268],{"class":267},[257,389,271],{"class":267},[257,391,275],{"class":274},[257,393,394],{"class":267},"https:\u002F\u002Fapi.openshield.dev\u002F1.0\u002Ftext\u002Fcheck-workflow.json",[257,396,281],{"class":274},[257,398,285],{"class":284},[257,400,401,403,405,408,410],{"class":259,"line":288},[257,402,291],{"class":267},[257,404,275],{"class":274},[257,406,407],{"class":267},"text=Write me at jane@example.com",[257,409,281],{"class":274},[257,411,285],{"class":284},[257,413,414,416,418,420,422],{"class":259,"line":303},[257,415,291],{"class":267},[257,417,275],{"class":274},[257,419,310],{"class":267},[257,421,281],{"class":274},[257,423,285],{"class":284},[257,425,426,428,430,432,434],{"class":259,"line":317},[257,427,291],{"class":267},[257,429,275],{"class":274},[257,431,324],{"class":267},[257,433,281],{"class":274},[257,435,285],{"class":284},[257,437,438,440,442,444,446],{"class":259,"line":331},[257,439,291],{"class":267},[257,441,275],{"class":274},[257,443,338],{"class":267},[257,445,341],{"class":284},[257,447,344],{"class":274},[120,449,450,451,453,454,456,457,460,461,464,465,467],{},"For an image, send either ",[124,452,158],{}," (the file) or ",[124,455,162],{}," (a public address, downloaded for you, with the ",[227,458,459],{"href":18},"same guards","). The ",[124,462,463],{},"GET"," form takes ",[124,466,162],{}," only, as a query string cannot carry a file.",[120,469,470,471,474,475,477,478,481],{},"The whole form must arrive within 10 seconds (",[124,472,473],{},"408 request_timeout"," otherwise), and every field but ",[124,476,158],{}," is limited to 64 KB. A text field holds up to the 20,000 characters of a ",[227,479,480],{"href":22},"text check"," (5,000 until your first top-up).",[243,483,485],{"id":484},"_2-create-the-workflows-you-used","2. Create the workflows you used",[120,487,488,489,495,496,499,500,241],{},"A SightEngine workflow is named in your calls. Create a workflow of the same name in the ",[227,490,494],{"href":491,"rel":492},"https:\u002F\u002Fwww.openshield.dev\u002Fdashboard\u002Fworkflows",[493],"nofollow","dashboard",", or use ",[124,497,498],{},"default",". The new workflow decides what is checked and how strictly: start from a template and adjust the ",[227,501,502],{"href":30},"thresholds",[243,504,506],{"id":505},"_3-map-the-category-ids","3. Map the category ids",[120,508,509,510,513,514,517,518,513,521,524,525,528,529,517,531,528,534,513,537,201,540,543,544,547,548,550,551,554,555,557],{},"The answer carries the fields of a SightEngine workflow answer: ",[124,511,512],{},"status",", ",[124,515,516],{},"request"," (",[124,519,520],{},"id",[124,522,523],{},"timestamp"," as a float of seconds, ",[124,526,527],{},"operations","), ",[124,530,166],{},[124,532,533],{},"{\"id\": \"\u003Cname>\"}",[124,535,536],{},"summary.action",[124,538,539],{},"summary.reject_prob",[124,541,542],{},"summary.reject_reason",", plus ",[124,545,546],{},"summary.review_reason",". Errors carry ",[124,549,516],{}," too. The categories are openmod's own: match on ",[124,552,553],{},"reject_reason[].id"," and never on the English ",[124,556,200],{},". Map each id to the message you show your users.",[120,559,560,561,513,564,513,567,513,570,513,573,513,576,201,579,582,583,513,586,513,589,513,592,513,595,513,598,513,601,513,603,513,606,513,609,513,612,513,615,513,618,201,621,624,625,627],{},"The ids you are most likely to meet are ",[124,562,563],{},"nudity",[124,565,566],{},"gore",[124,568,569],{},"weapon",[124,571,572],{},"hate_symbol",[124,574,575],{},"self_harm",[124,577,578],{},"drugs",[124,580,581],{},"minor"," for images, and ",[124,584,585],{},"text_unsafe",[124,587,588],{},"violence",[124,590,591],{},"sexual",[124,593,594],{},"hate",[124,596,597],{},"illegal",[124,599,600],{},"unethical",[124,602,575],{},[124,604,605],{},"pii_email",[124,607,608],{},"pii_phone",[124,610,611],{},"pii_iban",[124,613,614],{},"pii_card",[124,616,617],{},"spam",[124,619,620],{},"scam",[124,622,623],{},"link_unsafe"," for texts. ",[227,626,29],{"href":30}," lists where to see all of them.",[243,629,631],{"id":630},"what-differs","What differs",[633,634,635,655,658,680,690,700],"ul",{},[636,637,638,639,513,641,159,644,646,647,650,651,654],"li",{},"SightEngine's per-model score fields at the top level of the answer (such as ",[124,640,569],{},[124,642,643],{},"alcohol",[124,645,578],{},") are not served. The scores are in ",[124,648,649],{},"scores",", keyed by openmod's category ids, and ",[124,652,653],{},"reject_reason[].text"," is openmod's wording.",[636,656,657],{},"SightEngine's models and their other fields (faces, text in images, quality and the rest) are not served: a workflow here runs openmod's own categories.",[636,659,660,661,513,664,513,667,513,669,201,672,675,676,679],{},"The answer also carries openmod's own fields: ",[124,662,663],{},"request_id",[124,665,666],{},"workflow_version",[124,668,649],{},[124,670,671],{},"time_ms",[124,673,674],{},"ref",". A client may ignore them. ",[124,677,678],{},"request.operations"," is 1 for a check and 0 for a refusal.",[636,681,682,683,685,686,689],{},"The routes accept an optional ",[124,684,674],{}," field to attach your own id to a check; the ",[124,687,688],{},"\u002Fv1"," routes are the documented way to do it.",[636,691,692,693,696,697,241],{},"Errors use the ",[227,694,695],{"href":34},"openmod envelope",": ",[124,698,699],{},"{\"status\": \"failure\", \"error\": {\"type\", \"code\", \"message\"}}",[636,701,702,703,706],{},"The key is secret and server-side: a request that carries an ",[124,704,705],{},"Origin"," header is refused.",[120,708,709],{},"Sightengine is a trademark of its owner; openshield is not affiliated with it.",[711,712,713],"style",{},"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 .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}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);}",{"title":253,"searchDepth":288,"depth":288,"links":715},[716,717,718,719],{"id":245,"depth":288,"text":246},{"id":484,"depth":288,"text":485},{"id":505,"depth":288,"text":506},{"id":630,"depth":288,"text":631},"Three SightEngine workflow routes work here with the same paths, request fields and answer envelope. Change the base URL and key, map the category ids.","md",null,{},true,{"title":25,"description":720},"bolNbpNYQAVQ5huGEiunGo_PhH9HbXpWgaB52jUIqRo",[728,730],{"title":21,"path":22,"stem":23,"description":729,"children":-1},"Check a text with POST \u002Fv1\u002Ftext, for comments, messages, names and bios.",{"title":29,"path":30,"stem":31,"description":731,"children":-1},"A workflow decides which categories are checked and how strictly, with thresholds, custom categories and versions.",1793698847726]