Developer Reference

API Documentation

Integrate voice identity protection into your platform with our REST API. Base URL: https://api.voiceseal.io — every path below already includes the /api/v1 prefix (e.g. POST /api/v1/protect/pre-synthesis-check). Do not add /api/v1 twice.

Authentication

Endpoints require authentication — a JWT Bearer token (from login) or an X-API-Key for platform integrations. The production pre-synthesis check (POST /api/v1/protect/pre-synthesis-check) requires a key or token; a public, unauthenticated example is available at GET /api/v1/protect/demo/pre-synthesis-check for evaluation.

POST /auth/login
Content-Type: application/json

{
  "email": "[email protected]",
  "password": "your_password"
}

// Response
{
  "access_token": "eyJ...",
  "token_type": "bearer",
  "user_id": "uuid"
}

Include the token in all subsequent requests: Authorization: Bearer <token>

Voices

Enroll and manage voice prints.

POST /voices/enroll

Enroll a new voice. Requires multipart/form-data with audio file. Biometric consent must be granted first.

GET /voices

List all enrolled voices for the authenticated user.

DELETE /voices/{voice_id}

Remove an enrolled voice and all associated data.

Voice Identity Matching

Compare two audio samples for voice-identity similarity. VoiceSeal does not crawl or monitor platforms; provenance of synthetic audio is carried in-band via C2PA Content Credentials (transparency page).

POST /detection/compare

Submit two audio samples to compare voice-identity similarity. Returns a similarity score and a same-speaker assessment — evidence for review, not a verdict.

// Response
{
  "similarity": 0.94,
  "is_same_speaker": true,
  "embedding1_hash": "sha256:...",
  "embedding2_hash": "sha256:..."
}

Pre-Synthesis Check

The VoiceSeal pre-synthesis consent gate. Called by TTS platforms before generating audio to verify biometric identity, consent status, and license scope. This is VoiceSeal's patent-pending flagship capability. VoiceSeal provides an independent, synthesis-agnostic permission and provenance layer designed to operate across voice platforms rather than remaining limited to a single generator's ecosystem.

POST /api/v1/protect/pre-synthesis-check

Verify consent and license scope before synthesizing audio from a registered voice identity. Returns a single-use, time-limited authorization token on success, or authorization_denied on failure.

🔒 Authentication required — send an X-API-Key (platform integration) or a Bearer token (first-party). To try the gate without credentials, use the public GET /api/v1/protect/demo/pre-synthesis-check (evaluation only).

Platforms can evaluate VoiceSeal's consent gate before committing to an API integration via the public demo endpoint (GET /api/v1/protect/demo/pre-synthesis-check), which returns the same response schema. The production endpoint above requires authentication and writes a full audit record.

Request Body

{
  "voice_id": "string (UUID) — the enrolled voice identity to check",
  "platform_name": "string — identifying name of the calling platform",
  "intended_use": "string — commercial | audiobook | podcast | music | gaming",
  "license_token": "string (optional) — existing license token if already held"
}

Response — Approved (200)

{
  "status": "approved",
  "authorization_token": "string — single-use, time-limited token authorizing this synthesis (present only when approved). Deprecated alias: approval_token (retained until 2026-09-17)",
  "voice_id": "string",
  "consented": true,
  "licensed": true,
  "expires_at": "ISO 8601 timestamp",
  "check_id": "string — audit trail reference"
}

Response — Blocked (200)

{
  "status": "blocked",
  "action": "authorization_denied",
  "reason": "no_consent | no_license | scope_mismatch",
  "voice_id": "string",
  "license_url": "https://voiceseal.io/licensing?voice_id={voice_id}",
  "check_id": "string",
  "authorization_denied": true
}

Response — No registry record (200)

{
  "action": "no_registry_record",
  "platform_decision_required": true,
  "voice_id": null,
  "check_id": "string"
}

A voice with no registry record is not a 404 — the check returns 200 with action: no_registry_record and platform_decision_required: true, leaving the decision to your platform's standard terms.

Error Codes

403Platform not authorized
422Invalid request body
401Authentication required — missing/invalid X-API-Key or Bearer token
429Rate limit exceeded — 1,000 requests/minute (authenticated)

Audit record

Every decision — allow or deny — is written to the hash-chained audit log and addressable by its check_id (see GET /api/v1/protect/audit-log). A denial returns decision: "deny" with license_status/consent_status explaining why.

EU AI Act Article 50: The pre-synthesis check returns an authorization decision (and, when approved, a single-use authorization token) that your platform uses to gate synthesis; the decision is recorded in VoiceSeal's hash-chained audit log, addressable by check_id. Separately, VoiceSeal's C2PA marking applies a trusted, in-band AI-disclosure with a signature and RFC 3161 timestamp to marked audio. The C2PA manifest does not currently carry the authorization token, consent, license, or check_id — those live in the audit record, not the credential. (Planned, not yet available: embedding authorization references into the manifest to bind provenance to the consent record.)
GET /api/v1/protect/demo/pre-synthesis-check

🔓 Public, no auth. A self-describing demo of the pre-synthesis gate for platform evaluators — returns a live example request, the full response schema, and every possible action outcome, so you can see exactly what an integration looks like without enrolling a voice or authenticating first. Rate limit: 100 requests/hour per IP (unauthenticated).

Example Response (abridged)

{
  "demo": true,
  "endpoint": "POST /api/v1/protect/pre-synthesis-check",
  "response_schema": {
    "protected": "bool",
    "action": "authorized | authorization_denied | no_registry_record",
    "decision": "allow | deny | unresolved",
    "license_status": "licensed | unlicensed | not_applicable",
    "consent_status": "active | withdrawn | unknown",
    "platform_decision_required": "bool — true when no registry record exists",
    "license_url": "string | null",
    "check_id": "uuid — hash-chained audit-trail id"
  },
  "possible_responses": {
    "no_registry_record":   { "action": "no_registry_record", "decision": "unresolved", "platform_decision_required": true, "...": "..." },
    "protected_no_license": { "action": "authorization_denied", "decision": "deny", "license_status": "unlicensed", "license_url": "...", "...": "..." },
    "protected_licensed":   { "action": "authorized", "decision": "allow", "license_status": "licensed", "...": "..." }
  }
}

Try it live: GET https://api.voiceseal.io/api/v1/protect/demo/pre-synthesis-check

Webhooks

Subscribe to enrollment and licensing events. Every event originates from an action inside VoiceSeal — VoiceSeal does not crawl or monitor platforms — and each delivery is signed with HMAC-SHA256 (sent in the VoiceSeal-Event header).

// Registrable events
"enrollment.complete"   // a voice enrollment finished   (currently emitted)
"enrollment.ready"      // an enrollment session is ready to collect samples
"enrollment.failed"     // an enrollment could not complete
"license.renewed"       // a license was renewed
"license.expired"       // a license reached its expiry
"license.revoked"       // a license was revoked by the owner
"voice.deleted"         // a voice profile was deleted

// Example delivery
{
  "event": "enrollment.complete",
  "voice_id": "uuid",
  "timestamp": "2026-09-01T14:32:00Z"
}

Register via POST /webhooks/register with your endpoint URL, secret, and the events you want; deliveries are retried with backoff. enrollment.complete is live today; the remaining registrable events are emitted as their source actions are wired.

View Interactive Docs (Swagger)