Quick Start and API Docs

Base URL: https://veil-api.com  ·  Start free on the pricing page or browse the public examples repo.

Start Here

If you just want to see Veil working, this is the fastest path:

  1. Get a free API key from the pricing page.
  2. Keep your existing upstream provider key.
  3. Point your OpenAI-compatible client at https://veil-api.com/v1.

Minimal cURL test:

curl -X POST https://veil-api.com/v1/chat/completions \
  -H "Authorization: Bearer your-veil-key" \
  -H "x-upstream-key: your-openai-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [{"role": "user", "content": "Summarize: Customer John Smith (john@test.com, SSN 123-45-6789) wants a refund."}]
  }'

The upstream model sees placeholders, while your app gets the restored response back.

Get a Key

All API requests require a Veil API key in the Authorization header:

Authorization: Bearer your-veil-api-key

The easiest path is the signup box on the pricing page. If you want to request a verification link via API, use:

curl -X POST https://veil-api.com/v1/keys/create \
  -H "Content-Type: application/json" \
  -d '{"email": "you@company.com"}'

This returns 202 Accepted and emails a one-time verification link. If you are building your own signup flow, exchange the token for a key with:

curl -X POST https://veil-api.com/v1/keys/verify \
  -H "Content-Type: application/json" \
  -d '{"token": "email-verification-token"}'

Authentication

Every request to Veil should include:

HeaderRequiredDescription
AuthorizationYesYour Veil API key
x-upstream-keyUsuallyYour LLM provider API key for proxy requests
x-upstream-providerNoProvider name if you want something other than openai

Endpoints

POST /v1/chat/completions

OpenAI-compatible proxy. Strips PII from messages, forwards to your LLM provider, and restores PII in the response.

Headers: Authorization, x-upstream-key, and optionally x-upstream-provider.

Body: Standard OpenAI /v1/chat/completions request body. Supports stream: true.

Example:

curl -X POST https://veil-api.com/v1/chat/completions \
  -H "Authorization: Bearer your-veil-key" \
  -H "x-upstream-key: your-openai-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [{"role": "user", "content": "Summarize: Customer John Smith (john@test.com) wants a refund."}]
  }'

Response: Standard OpenAI response with PII restored, plus a veil field:

{
  "choices": [{"message": {"content": "John Smith requested a refund..."}}],
  "veil": {
    "entities_redacted": 2,
    "entity_types": ["PERSON", "EMAIL_ADDRESS"]
  }
}

POST /v1/redact

Standalone text redaction. No LLM call — just strip PII and return the result.

curl -X POST https://veil-api.com/v1/redact \
  -H "Authorization: Bearer your-veil-key" \
  -H "Content-Type: application/json" \
  -d '{"text": "Contact Sarah at sarah@test.com, SSN 078-05-1120"}'

Response:

{
  "redacted": "Contact <<VEIL_PERSON_a8f2c3d1e4f5>> at <<VEIL_EMAIL_ADDRESS_c3d1e4f5a8b2>>, SSN <<VEIL_US_SSN_9e7b1a2c3d4e>>",
  "entities_found": 3,
  "entity_types": ["PERSON", "EMAIL_ADDRESS", "US_SSN"]
}

GET /v1/usage

View your usage for the current billing period.

curl https://veil-api.com/v1/usage \
  -H "Authorization: Bearer your-veil-key"

Response:

{
  "period": "last_30_days",
  "requests": 142,
  "entities_redacted": 891,
  "tier": "starter"
}

GET /v1/providers

List all supported LLM providers.

curl https://veil-api.com/v1/providers

GET /health

Health check. Returns {"status": "ok"}.

Using with the OpenAI SDK

If your app already uses an OpenAI-compatible client, integration is usually just a base URL plus two headers.

Python:

from openai import OpenAI

client = OpenAI(
    api_key="your-openai-key",
    base_url="https://veil-api.com/v1",
    default_headers={
        "Authorization": "Bearer your-veil-key",
        "x-upstream-key": "your-openai-key",
    }
)

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Hi, I am Tom Ryan (tom@test.com)."}]
)

JavaScript:

import OpenAI from 'openai';

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: 'https://veil-api.com/v1',
  defaultHeaders: {
    'Authorization': `Bearer ${process.env.VEIL_API_KEY}`,
    'x-upstream-key': process.env.OPENAI_API_KEY,
  }
});

Switching Providers

You do not need to switch off Veil to change model vendors. Set x-upstream-provider to route to any supported provider:

curl -X POST https://veil-api.com/v1/chat/completions \
  -H "Authorization: Bearer your-veil-key" \
  -H "x-upstream-key: your-together-key" \
  -H "x-upstream-provider: together" \
  -H "Content-Type: application/json" \
  -d '{"model": "meta-llama/Llama-3-8b-chat-hf", "messages": [...]}'

Entity Types

Veil detects 79+ entity types across 18 countries:

Allowlisting

Skip specific entity types or values using headers:

curl -X POST https://veil-api.com/v1/chat/completions \
  -H "Authorization: Bearer your-veil-key" \
  -H "x-upstream-key: your-openai-key" \
  -H "x-veil-allow: PERSON,LOCATION" \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-4o-mini", "messages": [...]}'

Headers:

HeaderDescription
x-veil-allowComma-separated entity types to skip (e.g., PERSON,LOCATION)
x-veil-allow-valuesComma-separated specific strings to skip (e.g., Acme Corp,support@acme.com)

Audit Log

View your recent redaction history for compliance.

curl https://veil-api.com/v1/audit \
  -H "Authorization: Bearer your-veil-key"

Returns up to 100 entries with timestamps, entity counts, types, and model info.

Plans

TierRequests/monthPrice
Free100$0
Starter10,000$49/mo
Growth100,000$149/mo
Enterprise1,000,000+$499/mo

Start on the free tier, then upgrade in place when you are ready to put real traffic through it.

Error Reference

All errors return JSON with a detail field:

StatusMeaningExample detail
400Bad request"x-upstream-key header is required", "Unsupported provider: xyz", "Valid email address required", "Invalid or expired verification token"
401Auth failed"Missing Authorization header", "Invalid API key"
409Conflict"This email already has an account" (after successful email verification)
429Rate limited"Monthly request limit reached for free tier (100 requests)"

Upstream LLM errors are sanitized — you'll see "Upstream provider returned 4xx" without the raw provider error body.

Privacy

Veil never stores your message content or PII values. Only metadata (timestamps, entity counts, entity types) is logged. See our full Privacy Policy.