[{"data":1,"prerenderedAt":702},["ShallowReactive",2],{"navigation_docs":3,"-docs-migrating-from-sightengine":114,"-docs-migrating-from-sightengine-surround":697},[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":690,"extension":691,"links":692,"meta":693,"navigation":694,"path":26,"seo":695,"stem":27,"__hash__":696},"docs\u002Fdocs\u002F05.migrating-from-sightengine.md",{"type":117,"value":118,"toc":684},"minimark",[119,128,220,226,231,329,347,418,438,452,456,473,477,528,598,602,677,680],[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,180,195,205],"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],{},"The same path and the same query parameters.",[135,181,182,193],{},[150,183,184,155,187,190,191],{},[124,185,186],{},"POST \u002F1.0\u002Ftext\u002Fcheck-workflow.json",[124,188,189],{},"text"," and ",[124,192,166],{},[150,194,169],{},[135,196,197,202],{},[150,198,199],{},[124,200,201],{},"api_user",[150,203,204],{},"Accepted and ignored.",[135,206,207,212],{},[150,208,209],{},[124,210,211],{},"api_secret",[150,213,214,215,219],{},"Holds an openshield ",[216,217,218],"a",{"href":14},"API key",".",[120,221,222,223,219],{},"The base URL is ",[124,224,225],{},"https:\u002F\u002Fapi.openshield.dev",[227,228,230],"h2",{"id":229},"_1-point-the-client-at-the-new-base-url","1. Point the client at the new base URL",[232,233,238],"pre",{"className":234,"code":235,"language":236,"meta":237,"style":237},"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,239,240,270,285,299,313],{"__ignoreMap":237},[241,242,245,249,253,256,260,263,266],"span",{"class":243,"line":244},"line",1,[241,246,248],{"class":247},"sBMFI","curl",[241,250,252],{"class":251},"sfazB"," -X",[241,254,255],{"class":251}," POST",[241,257,259],{"class":258},"sMK4o"," \"",[241,261,262],{"class":251},"https:\u002F\u002Fapi.openshield.dev\u002F1.0\u002Fcheck-workflow.json",[241,264,265],{"class":258},"\"",[241,267,269],{"class":268},"sTEyZ"," \\\n",[241,271,273,276,278,281,283],{"class":243,"line":272},2,[241,274,275],{"class":251},"  -F",[241,277,259],{"class":258},[241,279,280],{"class":251},"media=@photo.jpg",[241,282,265],{"class":258},[241,284,269],{"class":268},[241,286,288,290,292,295,297],{"class":243,"line":287},3,[241,289,275],{"class":251},[241,291,259],{"class":258},[241,293,294],{"class":251},"workflow=default",[241,296,265],{"class":258},[241,298,269],{"class":268},[241,300,302,304,306,309,311],{"class":243,"line":301},4,[241,303,275],{"class":251},[241,305,259],{"class":258},[241,307,308],{"class":251},"api_user=ignored",[241,310,265],{"class":258},[241,312,269],{"class":268},[241,314,316,318,320,323,326],{"class":243,"line":315},5,[241,317,275],{"class":251},[241,319,259],{"class":258},[241,321,322],{"class":251},"api_secret=",[241,324,325],{"class":268},"$OPENSHIELD_API_KEY",[241,327,328],{"class":258},"\"\n",[232,330,332],{"className":234,"code":331,"language":236,"meta":237,"style":237},"curl \"https:\u002F\u002Fapi.openshield.dev\u002F1.0\u002Fcheck-workflow.json?url=https%3A%2F%2Fexample.com%2Fphoto.jpg&workflow=default&api_user=ignored&api_secret=$OPENSHIELD_API_KEY\"\n",[124,333,334],{"__ignoreMap":237},[241,335,336,338,340,343,345],{"class":243,"line":244},[241,337,248],{"class":247},[241,339,259],{"class":258},[241,341,342],{"class":251},"https:\u002F\u002Fapi.openshield.dev\u002F1.0\u002Fcheck-workflow.json?url=https%3A%2F%2Fexample.com%2Fphoto.jpg&workflow=default&api_user=ignored&api_secret=",[241,344,325],{"class":268},[241,346,328],{"class":258},[232,348,350],{"className":234,"code":349,"language":236,"meta":237,"style":237},"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,351,352,369,382,394,406],{"__ignoreMap":237},[241,353,354,356,358,360,362,365,367],{"class":243,"line":244},[241,355,248],{"class":247},[241,357,252],{"class":251},[241,359,255],{"class":251},[241,361,259],{"class":258},[241,363,364],{"class":251},"https:\u002F\u002Fapi.openshield.dev\u002F1.0\u002Ftext\u002Fcheck-workflow.json",[241,366,265],{"class":258},[241,368,269],{"class":268},[241,370,371,373,375,378,380],{"class":243,"line":272},[241,372,275],{"class":251},[241,374,259],{"class":258},[241,376,377],{"class":251},"text=Write me at jane@example.com",[241,379,265],{"class":258},[241,381,269],{"class":268},[241,383,384,386,388,390,392],{"class":243,"line":287},[241,385,275],{"class":251},[241,387,259],{"class":258},[241,389,294],{"class":251},[241,391,265],{"class":258},[241,393,269],{"class":268},[241,395,396,398,400,402,404],{"class":243,"line":301},[241,397,275],{"class":251},[241,399,259],{"class":258},[241,401,308],{"class":251},[241,403,265],{"class":258},[241,405,269],{"class":268},[241,407,408,410,412,414,416],{"class":243,"line":315},[241,409,275],{"class":251},[241,411,259],{"class":258},[241,413,322],{"class":251},[241,415,325],{"class":268},[241,417,328],{"class":258},[120,419,420,421,423,424,426,427,430,431,434,435,437],{},"For an image, send either ",[124,422,158],{}," (the file) or ",[124,425,162],{}," (a public address, downloaded for you, with the ",[216,428,429],{"href":18},"same guards","). The ",[124,432,433],{},"GET"," form takes ",[124,436,162],{}," only, as a query string cannot carry a file.",[120,439,440,441,444,445,447,448,451],{},"The whole form must arrive within 10 seconds (",[124,442,443],{},"408 request_timeout"," otherwise), and every field but ",[124,446,158],{}," is limited to 64 KB. A text field holds up to the 20,000 characters of a ",[216,449,450],{"href":22},"text check"," (5,000 until your first top-up).",[227,453,455],{"id":454},"_2-create-the-workflows-you-used","2. Create the workflows you used",[120,457,458,459,465,466,469,470,219],{},"A SightEngine workflow is named in your calls. Create a workflow of the same name in the ",[216,460,464],{"href":461,"rel":462},"https:\u002F\u002Fopenshield.dev\u002Fdashboard\u002Fworkflows",[463],"nofollow","dashboard",", or use ",[124,467,468],{},"default",". The new workflow decides what is checked and how strictly: start from a template and adjust the ",[216,471,472],{"href":30},"thresholds",[227,474,476],{"id":475},"_3-map-the-category-ids","3. Map the category ids",[120,478,479,480,483,484,487,488,483,491,494,495,498,499,487,501,498,504,483,507,190,510,513,514,517,518,520,521,524,525,527],{},"The answer carries the fields of a SightEngine workflow answer: ",[124,481,482],{},"status",", ",[124,485,486],{},"request"," (",[124,489,490],{},"id",[124,492,493],{},"timestamp"," as a float of seconds, ",[124,496,497],{},"operations","), ",[124,500,166],{},[124,502,503],{},"{\"id\": \"\u003Cname>\"}",[124,505,506],{},"summary.action",[124,508,509],{},"summary.reject_prob",[124,511,512],{},"summary.reject_reason",", plus ",[124,515,516],{},"summary.review_reason",". Errors carry ",[124,519,486],{}," too. The categories are openmod's own: match on ",[124,522,523],{},"reject_reason[].id"," and never on the English ",[124,526,189],{},". Map each id to the message you show your users.",[120,529,530,531,483,534,483,537,483,540,483,543,483,546,190,549,552,553,483,556,483,559,483,562,483,565,483,568,483,571,483,573,483,576,483,579,483,582,483,585,483,588,190,591,594,595,597],{},"The ids you are most likely to meet are ",[124,532,533],{},"nudity",[124,535,536],{},"gore",[124,538,539],{},"weapon",[124,541,542],{},"hate_symbol",[124,544,545],{},"self_harm",[124,547,548],{},"drugs",[124,550,551],{},"minor"," for images, and ",[124,554,555],{},"text_unsafe",[124,557,558],{},"violence",[124,560,561],{},"sexual",[124,563,564],{},"hate",[124,566,567],{},"illegal",[124,569,570],{},"unethical",[124,572,545],{},[124,574,575],{},"pii_email",[124,577,578],{},"pii_phone",[124,580,581],{},"pii_iban",[124,583,584],{},"pii_card",[124,586,587],{},"spam",[124,589,590],{},"scam",[124,592,593],{},"link_unsafe"," for texts. ",[216,596,29],{"href":30}," lists where to see all of them.",[227,599,601],{"id":600},"what-differs","What differs",[603,604,605,625,628,650,660,670],"ul",{},[606,607,608,609,483,611,159,614,616,617,620,621,624],"li",{},"SightEngine's per-model score fields at the top level of the answer (such as ",[124,610,539],{},[124,612,613],{},"alcohol",[124,615,548],{},") are not served. The scores are in ",[124,618,619],{},"scores",", keyed by openmod's category ids, and ",[124,622,623],{},"reject_reason[].text"," is openmod's wording.",[606,626,627],{},"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.",[606,629,630,631,483,634,483,637,483,639,190,642,645,646,649],{},"The answer also carries openmod's own fields: ",[124,632,633],{},"request_id",[124,635,636],{},"workflow_version",[124,638,619],{},[124,640,641],{},"time_ms",[124,643,644],{},"ref",". A client may ignore them. ",[124,647,648],{},"request.operations"," is 1 for a check and 0 for a refusal.",[606,651,652,653,655,656,659],{},"The routes accept an optional ",[124,654,644],{}," field to attach your own id to a check; the ",[124,657,658],{},"\u002Fv1"," routes are the documented way to do it.",[606,661,662,663,666,667,219],{},"Errors use the ",[216,664,665],{"href":34},"openmod envelope",": ",[124,668,669],{},"{\"status\": \"failure\", \"error\": {\"type\", \"code\", \"message\"}}",[606,671,672,673,676],{},"The key is secret and server-side: a request that carries an ",[124,674,675],{},"Origin"," header is refused.",[120,678,679],{},"Sightengine is a trademark of its owner; openshield is not affiliated with it.",[681,682,683],"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":237,"searchDepth":272,"depth":272,"links":685},[686,687,688,689],{"id":229,"depth":272,"text":230},{"id":454,"depth":272,"text":455},{"id":475,"depth":272,"text":476},{"id":600,"depth":272,"text":601},"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":690},"2Vd-HUHR5ut5IdrD9JiUfp7MEx_29nNplFVGeY3Z-cA",[698,700],{"title":21,"path":22,"stem":23,"description":699,"children":-1},"Check a text with POST \u002Fv1\u002Ftext, for comments, messages, names and bios.",{"title":29,"path":30,"stem":31,"description":701,"children":-1},"A workflow decides which categories are checked and how strictly, with thresholds, custom categories and versions.",1792938461960]