Build with AI
Feed the Stile docs to your AI assistant or coding agent — llms.txt, a full-corpus file, and the OpenAPI spec.
Most Stile integrations are now written with an AI assistant in the loop. These docs are published in machine-friendly formats so your assistant works from the real API surface instead of guessing:
| Resource | URL | What it is |
|---|---|---|
llms.txt | docs.stile.id/llms.txt | Index of every docs page with descriptions, per the llms.txt convention. |
llms-full.txt | docs.stile.id/llms-full.txt | The complete public integration documentation as one markdown file. |
| OpenAPI 3.1 spec | docs.stile.id/openapi.yaml | Machine-readable schema for the documented public integration surface. |
Using them
Coding agents (Claude Code, Codex, Cursor, Copilot Workspace) — point the agent at https://docs.stile.id/llms-full.txt in your prompt, or download it into the repo so it's part of the agent's searchable context:
curl -o docs/stile-docs.md https://docs.stile.id/llms-full.txtChat assistants (Claude, ChatGPT) — paste the contents of llms-full.txt into the conversation (or attach it as a file), then describe your stack and what you're building.
Cursor — add https://docs.stile.id/llms-full.txt as a custom docs source (Settings → Indexing & Docs), then reference it with @Docs in chat.
SDK generators and API tooling — consume https://docs.stile.id/openapi.yaml directly.
Starter prompt
A prompt that reliably produces a working integration. Replace the bracketed backend with your own:
You are integrating Stile age verification (docs: https://docs.stile.id/llms-full.txt).
My backend: [LANGUAGE, FRAMEWORK, AND DEPLOYMENT PLATFORM].
My workflow ID: wf_YOUR_WORKFLOW_ID (already published in the Stile dashboard).
Build:
1. An authenticated, per-user-rate-limited POST /api/start-verification route.
Read orderId from the session-url path/query and load an order owned by the
authenticated user. Using the backend's standard HTTP client, POST
https://api.stile.id/v1/verification_sessions with Authorization: Bearer
STILE_API_KEY, Content-Type: application/json, a stable Idempotency-Key,
and { type: "age", workflow_id, email: authenticatedUser.email,
client_reference_id: order.id }. Store session.id on the order, and return
{ session_id, client_secret, methods, age_tier }. Do not install or import
@stile/node.
2. A checkout page that loads https://js.stile.id/v1/stile.js and renders
<stile-frame mode="modal"
session-url="/api/start-verification?orderId=order_123"
workflow-id="wf_YOUR_WORKFLOW_ID">.
3. A POST /api/webhooks route that reads the raw body before JSON parsing.
Parse t and v1 from Stile-Signature, reject timestamps more than 300
seconds from the current time, compute lowercase hex
HMAC-SHA256(STILE_WEBHOOK_SECRET,
"{t}.{raw_body}"), and compare in constant time. Reject failures with 400.
Read the session from event.data.object. In one database transaction, claim
unique event.id and update only the pending order whose stored session ID
and id/client_reference_id both match. Return 500 if persistence fails so
Stile retries.
Rules: use direct HTTPS from any backend. @stile/node is not a public npm
package, so do not generate an install command or SDK import unless package
access is explicitly confirmed. Never trust the client-side stile:verified
event for fulfillment; use only the signed webhook. Use stile_sk_ keys and
test against the 500-session monthly sandbox quota. Never expose the secret
key to the browser.Canonical integration facts
- Webhook resources are always nested at
event.data.object; never useevent.data.id. - The supported public backend path is direct HTTPS to
https://api.stile.id/v1/from any language.@stile/nodeis an unpublished private preview, so agents must not generate package installation or imports without confirmed access. - Deduplicate business work on
event.id. Automatic and manual retries reuse the delivery record ID; another subscribed endpoint has its own delivery record for the same event. - Stile automatically retries webhook delivery for
429,5xx, network failures, and timeouts. Other4xxresponses are permanent failures. - The browser's
stile:verifiedevent, redirect query parameters, and injected form fields are not proof. Fulfill only from state written by a verified webhook. - Primary widget paths are
mdlanddocument_capture, plusnfc_passportin supported native embeds.selfie_livenessandselfie_matchare active layers;self_attestationis an additional declaration and must not be the only hosted-widget path.ip_analysis,device_risk, andgeolocationare passive supplementary checks. Publishing rejectsmid,eudi_pid,facial_age,carrier_lookup,open_banking,parental_consent,student, and standaloneapple_walletsteps as not implemented. - Session expiry defaults to 24 hours but can be overridden by the workflow.
under_reviewis a real non-terminal hold state. - For
429, wait the number of seconds inRetry-Afterbefore retrying. Retry network failures and temporary5xxresponses with bounded exponential backoff, while reusing the sameIdempotency-Key.
Keep your assistant honest
The API requires workflow_id on every session and rejects a per-request methods array — models
trained on older API shapes sometimes invent use_case or products parameters. If the generated
code passes those, it predates the workflow model; re-point the assistant at the docs above.