HTTP Integration
Use direct HTTP calls when you need full control, a language without an official SDK, or custom retry/idempotency logic.
Authentication
Pass your API key in one of the following headers:
Authorization: Bearer <API_KEY>X-API-Key: <API_KEY>
Never expose the key in browser code, mobile apps, or public repositories.
Base URL
| Environment | URL |
|---|---|
| SaaS production | https://app.veilio.fr/api |
| On-premise | https://<your-domain>/api |
| Local development | http://localhost:3000/api |
Use
https://app.veilio.fr/api, notapi.veilio.com.
Supported data types (type field)
The type field is optional but recommended for audit, SIEM events, and dashboard filtering.
| Type | Example |
|---|---|
email | john@example.com |
phone | +33612345678 |
ssn | 123-45-6789 |
iban | FR7630006000011234567890189 |
address | 10 rue de la Paix, Paris |
firstName / lastName | Personal names |
birthdate | 1990-01-15 |
| Custom string | Any label your app uses consistently |
Core endpoints
| Method | Path | Description |
|---|---|---|
| POST | /tokenize | Single field |
| POST | /tokenize/bulk | Batch fields (max 1,000 per call) |
| POST | /tokenize/format | JSON / CSV / SQL in-place |
| POST | /detokenize | Reveal one token |
| POST | /detokenize/bulk | Reveal many tokens (max 1,000 per call) |
| POST | /detokenize/format | Restore structured data |
| POST | /tokens/shred | Irreversible crypto-shred |
| POST | /flows/ingest | Form / lead JSON ingestion |
See the full API Reference for dashboard, dataset, and compliance routes.
Tokenize
curl -s -X POST "$VEILIO_BASE_URL/tokenize" \
-H "Authorization: Bearer $VEILIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": "support@veilio.fr",
"type": "email",
"metadata": { "entityId": "customer_42", "source": "signup" },
"retention": { "ttlDays": 365 }
}'Request body
| Field | Required | Description |
|---|---|---|
data | Yes | Sensitive string to tokenize |
type | No | Data category (see table above) |
mode | No | fpt returns a format-preserving mask. Omitted or standard returns tok_… |
entityId | No | Partner id. Required when mode is fpt |
metadata | No | Arbitrary JSON (e.g. entityId for profile grouping) |
retention | No | { "ttlDays": 30 } or { "retentionUntil": "2026-12-31T2359.000Z" } |
Response 200
{
"token": "tok_abc123...",
"createdAt": "2026-03-26T1000.000Z",
"retentionUntil": "2027-03-26T1000.000Z"
}Detokenize
curl -s -X POST "$VEILIO_BASE_URL/detokenize" \
-H "Authorization: Bearer $VEILIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"token": "tok_abc123...",
"reason": "Support ticket resolution"
}'Response 200
{
"data": "support@veilio.fr",
"accessedAt": "2026-03-26T1000.000Z"
}Response 410 — token was cryptographically shredded (TOKEN_SHREDDED).
Bulk tokenize
curl -s -X POST "$VEILIO_BASE_URL/tokenize/bulk" \
-H "Authorization: Bearer $VEILIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"entityId": "BP10042",
"fields": [
{ "data": "support@veilio.fr", "type": "email", "mode": "fpt" },
{ "data": "+33601020304", "type": "phone", "mode": "fpt", "retention": { "ttlDays": 90 } },
{ "data": "Ada Lovelace", "type": "firstName" }
]
}'A field without mode stays tok_…. A field with "mode": "fpt" returns the mask and needs entityId on the field or on the request. Two fields of the same type and the same entityId share one mask: the second clear replaces the first in the vault.
Response 201
{
"tokens": [
{ "token": "00000000@example.com", "type": "email", "createdAt": "...", "retentionUntil": null },
{ "token": "0600000000", "type": "phone", "createdAt": "...", "retentionUntil": "..." },
{ "token": "tok_...", "type": "firstName", "createdAt": "...", "retentionUntil": null }
],
"summary": { "total": 3, "success": 3, "failed": 0 },
"createdAt": "2026-03-26T1000.000Z"
}Partial failures include an errors array with { "field": 0, "error": "..." }.
Bulk detokenize
curl -s -X POST "$VEILIO_BASE_URL/detokenize/bulk" \
-H "Authorization: Bearer $VEILIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"entityId": "BP10042",
"tokens": [
{ "token": "00000000@example.com" },
{ "token": "0600000000" },
{ "token": "000000000", "type": "siren" },
{ "token": "tok_def...", "reason": "Profile view" }
],
"reason": "Profile view"
}'The top-level reason is optional. It creates one audit log line for the whole batch. A mask needs entityId. Nine zeros need type (siren or postal).
Response 200
{
"results": [
{ "token": "tok_abc...", "data": "support@veilio.fr", "accessedAt": "..." }
],
"summary": { "total": 2, "success": 2, "failed": 0 },
"accessedAt": "2026-03-26T1000.000Z"
}Tokenize format (JSON, CSV, SQL)
curl -s -X POST "$VEILIO_BASE_URL/tokenize/format" \
-H "Authorization: Bearer $VEILIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": "{\"email\":\"john@example.com\",\"phone\":\"+33612345678\"}",
"format": "json",
"options": {
"fields": ["email"],
"retention": { "ttlDays": 365 }
},
"entityId": "customer_42"
}'Response 200
{
"format": "json",
"tokenizedData": "{\"email\":\"tok_...\",\"phone\":\"+33612345678\"}",
"tokens": [
{ "path": "email", "token": "tok_...", "type": "email" }
],
"summary": { "totalFields": 2, "tokenizedFields": 1 }
}CSV options: options.csv.delimiter, options.csv.hasHeaders (set false when the file has no header row). SQL support is INSERT … VALUES only; UPDATE returns 400 No fields found to tokenize.
Detokenize format
POST /detokenize/format restores tok_… values produced by /tokenize/format. It does not reveal FPT masks (00000000@example.com, 0600000000, 000000000, …). For masks, use POST /detokenize or POST /detokenize/bulk with entityId (and type when the mask shape is shared, e.g. SIREN vs postal code).
curl -s -X POST "$VEILIO_BASE_URL/detokenize/format" \
-H "Authorization: Bearer $VEILIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tokenizedData": "{\"email\":\"tok_abc123...\"}",
"format": "json",
"tokens": [{ "path": "email", "token": "tok_abc123..." }]
}'Response 200
{
"format": "json",
"detokenizedData": "{\"email\":\"john@example.com\"}",
"summary": { "tokensProcessed": 1 }
}Shred a token
Immediately and irreversibly destroy a token (GDPR erasure, right to be forgotten). Prefer this for masks and token strings; DELETE /tokens/[id] also accepts an API key when you already have the internal id.
curl -s -X POST "$VEILIO_BASE_URL/tokens/shred" \
-H "Authorization: Bearer $VEILIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"token": "tok_xxxxxxxxxxxx",
"reason": "GDPR - user deletion request"
}'Response 200
{
"token": "tok_xxxxxxxxxxxx",
"shreddedAt": "2026-03-26T1000.000Z"
}Flow ingest (form / lead payloads)
Tokenize a JSON object in one call — useful for signup forms, CRM webhooks, or lead capture. Uses the tokenization schema attached to your API key (if configured).
curl -s -X POST "$VEILIO_BASE_URL/flows/ingest" \
-H "Authorization: Bearer $VEILIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"flowId": "signup-v1",
"source": "website",
"entityId": "lead_9912",
"data": {
"email": "john@example.com",
"phone": "+33612345678",
"company": "Acme Corp"
},
"metadata": { "utm_source": "google" }
}'Response 201
{
"flowId": "signup-v1",
"protectedData": {
"email": "tok_...",
"phone": "tok_...",
"company": "Acme Corp"
},
"tokens": [
{ "path": "email", "token": "tok_...", "type": "email" },
{ "path": "phone", "token": "tok_...", "type": "phone" }
],
"lookup": {
"email_hash": "...",
"phone_hash": "..."
},
"policyApplied": "api_key_schema",
"metadata": { "source": "website", "originalMetadata": { "utm_source": "google" } }
}Store protectedData in your database. Fields not covered by your API key schema remain in plaintext.
Response and retry strategy
| HTTP | Code | Action |
|---|---|---|
| 401 | AUTH_ERROR | Fix or rotate API key |
| 400 | VALIDATION_ERROR | Fix request body |
| 403 | PLAN_LIMIT | Check usage / upgrade plan |
| 410 | TOKEN_SHREDDED | Data is gone — do not retry |
| 429 | RATE_LIMIT_ERROR | Honor Retry-After, exponential backoff |
| 5xx | INTERNAL_ERROR | Retry with backoff |
- Handle
429with exponential backoff. - Read the
Retry-Afterheader before retrying. - Use bulk endpoints for high-throughput imports.
- Add idempotency in your app for replayed business operations.
Related links
- SDK Javascript · SDK Python
- API Reference
- Troubleshooting