SOPHIA XT

Gate API

Put the gate in front of anything you send out.

Two calls. protect swaps client data for placeholders before your text goes to an AI, a vendor or a log. restore puts the real values back into whatever comes back. The same industry rules, names settings and client list as your firm's desk apply.

Keys

An owner creates keys in Owner view, API tab. A key is shown once; we keep only a hash of it. Send it on every request:

Authorization: Bearer sdk_…

Keys act for the firm that made them. Revoke a key and it stops working immediately. Keep keys on your server; never put one in a web page or a mobile app.

POST /api/v1/protect

curl https://desk.sophiaxt.com/api/v1/protect \
  -H "Authorization: Bearer $SAFE_DESK_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "Client Dana Reyes, SSN 123-45-6789, needs a letter."}'

Response:

{
  "outcome": "alerted",
  "protected_text": "Client [NAME_1], SSN [SSN_1], needs a letter.",
  "findings": [
    { "rule": "ssn",  "label": "Social Security number",   "action": "alert" },
    { "rule": "name", "label": "Person's name (detected)", "action": "redact" }
  ],
  "vault": "v1.…"
}
FieldMeaning
outcomeclean, redacted, alerted (the owner was notified) or blocked.
protected_textThe text to send onward. null when blocked: passwords, keys and privileged material are never returned.
findingsWhat was caught, by rule. Never the values.
vaultThe swap table, sealed with AES-256-GCM and bound to your firm. You can't read it and neither can anyone you pass it to. Send it back with the next protect call in the same conversation so the same value keeps the same placeholder, and with restore.

POST /api/v1/restore

curl https://desk.sophiaxt.com/api/v1/restore \
  -H "Authorization: Bearer $SAFE_DESK_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "Letter for [NAME_1] ([SSN_1]).", "vault": "v1.…"}'
{ "text": "Letter for Dana Reyes (123-45-6789)." }

A full round trip in JavaScript

const gate = (path, body) => fetch(`https://desk.sophiaxt.com/api/v1/${path}`, {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.SAFE_DESK_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify(body),
}).then((r) => r.json());

const p = await gate("protect", { text: userText });
if (p.outcome === "blocked") throw new Error("Stopped by Safe-Desk: " + p.findings.map((f) => f.label).join(", "));
const answer = await yourModel(p.protected_text);          // your AI never sees the values
const { text } = await gate("restore", { text: answer, vault: p.vault });

Errors and limits

StatusCodeMeaning
400bad_request, bad_vaultMissing fields, or a vault your firm didn't issue or that was altered.
401unauthorizedMissing, wrong or revoked key.
402The firm's subscription isn't active.
413too_largeText over 100,000 characters.
429rate_limitedOver 600 requests a minute for one key. Retry after the Retry-After seconds.

Metering

Text through protect counts toward your firm's included AI allowance at about four characters a token, the same pool as the desk: 2 million tokens per staff member a month. Beyond that, $2 per million tokens. restore is not metered. Usage is on the Billing tab.

What the API stores

Nothing you send. The text, the protected text and the values are never written to our database or logs. Your owner's log records that a call was made, by which key's account, and which rules fired. All traffic is HTTPS.