How it works
Quick integration
1. Register your service
Services are self-serve. First create a webhook endpoint subscribed togate.session.approved, then register your service through the dashboard or by POSTing to /v1/gate/services with a secret key that has the gate:services:manage scope. Each organization can own up to 5 Gate services.
From the dashboard — go to dashboard.usefoil.com/gate/new, fill in the fields below, and click Create.
From the API — send the same fields as JSON:
idis the public slug used everywhere, includingnpx signup <id>. Lowercase,3–32chars,a–z/0–9/_/-, must start and end with a letter or number. Reserved IDs cannot be claimed:gate,registry,services,service,login,sessions,session,tokens,token,webhook,auth.webhook_endpoint_idis required. Create and manage endpoints, subscriptions, signing secrets, test sends, and event history in Webhooks.websiteis required.env_varsdeclares the keys your webhook will deliver. The Gate-managed<ID>_GATE_AGENT_TOKENis added automatically whendashboard_login_urlis set — don’t declare it yourself.discoverable: trueis required for the service to appear inGET /v1/gate/registry.
sdks entries, branding.ascii_art, and the PATCH shape for updates.
2. Implement your webhook
Gate calls your webhook when a user approves signup. Your webhook creates the account and returns an encrypted output bundle for the CLI’s public key. Webhook handlers must be idempotent bygate_session_id: retries must return the exact same encrypted bundle instead of creating a second account.
Gate uses one mandatory delivery algorithm for every integration:
x25519-hkdf-sha256/aes-256-gcmdelivery.public_keyis a raw X25519 public key encoded as base64urldelivery.key_idis the base64url SHA-256 fingerprint of that raw public key
- verify the raw-body webhook signature
- validate the approved webhook payload
- return plaintext
outputsand let the helper build the encrypted response
3. Gate-managed login token (optional)
If your service setsdashboard_login_url, Gate also delivers a Gate-owned login token alongside your customer env vars. The CLI writes it to .env under a derived key:
foil→FOIL_GATE_AGENT_TOKENacme-prod→ACME_PROD_GATE_AGENT_TOKEN
npx signup <service> login. It is Gate-managed, is not configured through your service env_vars, and is not exposed in the public registry as editable metadata.
4. Dashboard login (optional)
Gate also supportsnpx signup yourproduct login, which starts a fresh Gate approval flow for dashboard access. Set dashboard_login_url in your registry entry, then add one route to your dashboard:
Webhook payload
When a user approves signup, Gate sends:| Field | Description |
|---|---|
type | Always gate.session.approved for this event. |
data.service_id | The registry service being provisioned. Use it if one webhook handles multiple services. |
data.gate_session_id | Stable idempotency key for this signup attempt. Persist and reuse it on retries. |
data.gate_account_id | Stable identifier for this signup. Use it to link to your internal account. |
data.account_name | The name the developer chose (defaults to their project directory name). |
data.metadata | Optional key-value pairs passed during session creation. |
data.delivery | CLI-provided encrypted delivery metadata. Always encrypt your env map to this key. |
data.foil.verdict | human, bot, or inconclusive. |
data.foil.score | Risk score from 0 (human) to 1 (bot). |
env_vars configuration. Gate keeps using that schema internally for CLI validation, but ownership stays internal to Gate and is no longer sent on webhook calls or public registry responses.
Webhook response
Your webhook must return:.env, and then acknowledges receipt so Gate can purge the stored envelopes.
Onboarding links like docs_url are owned by the registry entry for the service, not by the webhook response.
Security
- Webhook signatures: Every webhook is signed with HMAC-SHA256 over
${timestamp}.${rawBody}. Always verify bothX-Foil-TimestampandX-Foil-Signatureagainst the raw request body. - Webhook idempotency: Treat
gate_session_idas the provisioning idempotency key. Retries must return the same encrypted delivery bundle. - Agent tokens: Gate-owned
agt_tokens. Verified via Gate’s API. Can be revoked instantly. - Mandatory encrypted handoff: Gate never stores plaintext integrator credentials. Your webhook returns ciphertext for the CLI’s public key.
- Ack-based delivery: Approved sessions can safely re-poll the same ciphertext until the CLI acknowledges receipt. Gate purges stored envelopes after a valid ack or after the 24-hour delivery TTL.
- Foil scoring: Every signup is scored by Foil’s bot detection. Bot verdicts are automatically blocked.
- Session expiry: Gate sessions expire after 15 minutes.