Documentation
Using the Safety Gate via HTTP API

Using the Safety Gate via HTTP (No n8n Required)

[← Back to Docs](/docs)

This page is the primary reference for integrating AI Safety Gate into any app.

All examples use the production base URL:

https://aisafegate.com

API reference (copy/paste)

`POST https://aisafegate.com/api/validate`

**Purpose**

Validate AI output (and its context) before you execute a real-world action.

**Request (curl)**

curl -X POST "https://aisafegate.com/api/validate" \
  -H "Authorization: Bearer REPLACE_ME" \
  -H "Content-Type: application/json" \
  -d '{
    "ai_output": "Draft an email confirming a refund.",
    "context": {
      "actionKind": "llm_output",
      "actionType": "llm_text"
    }
  }'

**Responses (examples)**

PASS:

{
  "status": "PASS",
  "decision_id": null
}

WARN (requires approval polling):

{
  "status": "WARN",
  "decision_id": "dec_123",
  "approval_token": "appr_abc"
}

BLOCK:

{
  "status": "BLOCK",
  "decision_id": "dec_456"
}

**What to do next**

  • If PASS, you may execute the downstream action.
  • If WARN, you must pause and poll approval (see below). Do not execute unless you receive { "approved": true }.
  • If BLOCK, do not execute the downstream action.
  • If the API request fails, fail closed (treat as not approved / do not execute).

`GET https://aisafegate.com/api/decisions/{decision_id}/approval?approval_token=...`

**Purpose**

Check whether a WARN decision has been approved.

**Request (curl)**

curl "https://aisafegate.com/api/decisions/dec_123/approval?approval_token=appr_abc" \
  -H "Authorization: Bearer REPLACE_ME"

**Response (example)**

Approved:

{
  "approved": true
}

Not approved yet:

{
  "approved": false
}

**What to do next**

  • If { "approved": true }, you may execute the paused action.
  • If { "approved": false }, keep waiting (or stop on your timeout). Timeout is not approval.
  • If this request fails, treat it as { "approved": false } (fail closed).

1) Minimal Working Example (Node.js)

If you copy this example and replace the API key, it will work.

// Node.js 18+
// 1) Replace with your API key
const API_KEY = "REPLACE_ME";

const BASE_URL = "https://aisafegate.com";

const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function validate(ai_output) {
  const res = await fetch(`${BASE_URL}/api/validate`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${API_KEY}`,
    },
    body: JSON.stringify({
      ai_output,
      context: {
        actionKind: "llm_output",
        actionType: "llm_text",
      },
    }),
  });

  if (!res.ok) {
    throw new Error(`validate failed: ${res.status} ${await res.text()}`);
  }

  return res.json();
}

async function pollApproval({ decision_id, approval_token, timeoutMs = 5 * 60 * 1000 }) {
  const startedAt = Date.now();

  while (Date.now() - startedAt < timeoutMs) {
    const url = new URL(`${BASE_URL}/api/decisions/${decision_id}/approval`);
    url.searchParams.set("approval_token", approval_token);

    const res = await fetch(url, {
      headers: {
        Authorization: `Bearer ${API_KEY}`,
      },
    });

    if (!res.ok) {
      // Fail closed: errors are never approval.
      return { approved: false };
    }

    const data = await res.json();
    if (data && data.approved === true) return { approved: true };

    // Not approved yet
    await sleep(2000);
  }

  // Timeout is NOT approval.
  return { approved: false };
}

async function main() {
  const ai_output = "Draft an email to the customer confirming a refund.";

  // Step A: validate
  let decision;
  try {
    decision = await validate(ai_output);
  } catch (e) {
    // Fail closed: do not execute if validation cannot be completed safely.
    console.error(String(e));
    process.exitCode = 1;
    return;
  }

  // Step B: enforce
  if (decision.status === "PASS") {
    console.log("PASS → continue");
    // Execute your action here
    return;
  }

  if (decision.status === "BLOCK") {
    console.log("BLOCK → stop");
    return;
  }

  if (decision.status === "WARN") {
    console.log("WARN → pause and wait for approval");

    const { approved } = await pollApproval({
      decision_id: decision.decision_id,
      approval_token: decision.approval_token,
      timeoutMs: 5 * 60 * 1000,
    });

    if (approved) {
      console.log("Approved → continue");
      // Execute your action here
      return;
    }

    console.log("Not approved (or timed out) → stop");
    return;
  }

  // Unknown status: fail closed
  console.log("Unknown decision → stop");
}

main();

2) Minimal Working Example (Python)

If you copy this example and replace the API key, it will work.

# Python 3.9+
import time
import requests

API_KEY = "REPLACE_ME"
BASE_URL = "https://aisafegate.com"

def validate(ai_output: str):
    res = requests.post(
        f"{BASE_URL}/api/validate",
        headers={
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json",
        },
        json={
            "ai_output": ai_output,
            "context": {"actionKind": "llm_output", "actionType": "llm_text"},
        },
        timeout=20,
    )

    if not res.ok:
        raise RuntimeError(f"validate failed: {res.status_code} {res.text}")

    return res.json()

def poll_approval(decision_id: str, approval_token: str, timeout_s: int = 300):
    started = time.time()
    while time.time() - started < timeout_s:
        res = requests.get(
            f"{BASE_URL}/api/decisions/{decision_id}/approval",
            params={"approval_token": approval_token},
            headers={"Authorization": f"Bearer {API_KEY}"},
            timeout=20,
        )

        # Fail closed: errors are never approval.
        if not res.ok:
            return {"approved": False}

        data = res.json()
        if data and data.get("approved") is True:
            return {"approved": True}

        time.sleep(2)

    # Timeout is NOT approval.
    return {"approved": False}

def main():
    ai_output = "Draft an email to the customer confirming a refund."

    try:
        decision = validate(ai_output)
    except Exception:
        # Fail closed
        return

    if decision.get("status") == "PASS":
        # Execute your action here
        return

    if decision.get("status") == "BLOCK":
        return

    if decision.get("status") == "WARN":
        approved = poll_approval(decision["decision_id"], decision["approval_token"])['approved']
        if not approved:
            return
        # Execute your action here
        return

if __name__ == "__main__":
    main()

3) WARN Approval Handling (mandatory)

When you receive WARN:

  • Your app must **pause** the downstream action.
  • Your app may **resume** only after polling returns { "approved": true }.
  • A timeout is **not** approval.
  • Errors must **fail closed** (do not continue).

Polling endpoint:

GET https://aisafegate.com/api/decisions/{decision_id}/approval?approval_token=...

4) Execution Safety Rules

  • Never assume approval.
  • Never auto-approve.
  • Never skip polling for WARN.
  • Never continue on error.
  • If validation fails, stop.
Disclaimer
This documentation is provided for general information only. It is not legal advice, not a guarantee of compliance, and not a substitute for your own security review. You are responsible for evaluating and meeting any legal, regulatory, and contractual obligations applicable to your use case.