Integration guides
Supabase Edge Functions
Moderate content from a Supabase Edge Function, with the key as a project secret.
An Edge Function runs on the server, so it is the right place for the key. Call it from your app, and let it call openshield.
Set the key as a secret
supabase secrets set OPENMOD_API_KEY=om_live_...
Read it in the function with Deno.env.get("OPENMOD_API_KEY"). Never put it in the code of your front end.
The function
supabase/functions/moderate-text/index.ts
const base = "https://api.openshield.dev"
Deno.serve(async (request) => {
const { text, ref } = await request.json()
let answer: Response
try {
answer = await fetch(`${base}/v1/text`, {
method: "POST",
headers: {
Authorization: `Bearer ${Deno.env.get("OPENMOD_API_KEY")}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ text, ref }),
signal: AbortSignal.timeout(10_000),
})
} catch {
// The check could not be made: fail closed, keep the content hidden.
return Response.json({ decision: "hold" })
}
const body = await answer.json()
if (!answer.ok) {
const refused = [400, 413, 415].includes(answer.status)
return Response.json({ decision: refused ? "refuse" : "hold", error: body?.error?.type ?? "unknown" })
}
const { action, reject_reason } = body.summary
return Response.json({
decision: action === "accept" ? "publish" : action === "review" ? "hold" : "refuse",
// Choose your user's message from this id, in your own words.
reason: reject_reason[0]?.id ?? null,
requestId: body.request_id,
})
})
Deploy it with supabase functions deploy moderate-text. Your app calls it with the Supabase client:
const { data } = await supabase.functions.invoke("moderate-text", { body: { text, ref: commentId } })
Your function is the one that calls openshield, from the Supabase servers. The browser calls your function, never openshield: a request to our API with an
Origin header is refused.