VoidhashDocs
DocumentationAPI reference
Dashboard
Essentials
API overview
Authentication
Endpoints
Ad_accounts
Analytics
Api_keys
Auth
Component_dev_sessions
Component_registry
Components
Development
Events
Experiments
Feature_flag_overrides
Feature_flag_targets
Feature_flags
Ingest_policy
Notification_sends
Notifications
Organizations
Payment_provider_configurations
Payment_provider_products
Payment_sources
Paywall_locations
Paywalls
Perks
Persons
Products
Projects
Push_notification_configurations
Schema
Sdk
Users
Webhooks
Analytics
Event capture

Authentication

Choose the right credential for server, tool, or device requests.

Every request to the Voidhash API carries a credential. Voidhash has three programmatic credential types, each meant for a different kind of caller. Use the narrowest one that fits.

CredentialHeaderUse
User API keyx-api-keyCLI and tools acting as a signed-in user across projects.
Project secret keyx-secret-keyServer-to-server requests for one project, including event capture.
Publishable keyx-publishable-key + x-distinct-idOfficial SDKs and distributed clients.

Project secret keys

A project secret key authorizes your backend to act on one project. Send it in the x-secret-key header:

curl https://api.voidhash.com/api/v1/persons \
  -H "x-secret-key: $VOIDHASH_SECRET_KEY"
Never expose a secret key

A project secret key grants broad access to the project. Do not put it in a mobile app, web bundle, public repository, or analytics event property. Rotate it immediately after exposure.

Limit what a secret key can do

By default, a secret key has full access to its project. When you create one, you can limit it to a set of project permissions instead, so a key handed to a reporting job or an AI agent can only read what it needs. In the dashboard, choose an access level under Settings → API keys → New secret key:

AccessPermissionsAllows
Full accessEvery project permissionEverything the API offers for the project.
Read-only analyticsproject:read, project:analytics:read, project:ads:readReading the project, its analytics insights and reports, and its connected ad accounts and campaigns, over the API and MCP.

Through the API, pass the permissions as scopes when you create the key:

curl https://api.voidhash.com/api/v1/api-keys \
  -H "x-secret-key: $VOIDHASH_SECRET_KEY" \
  -H "content-type: application/json" \
  -d '{
    "name": "Reporting",
    "projectId": "proj_...",
    "scopes": ["project:read", "project:analytics:read", "project:ads:read"]
  }'

A key's scopes are fixed when it is created. Rotating the key keeps them, and nothing can widen them later; create a new key when you need different access. A key never gets a permission that the user or key creating it does not have. Listing keys returns each key's scopes, which is null for a full-access key.

Rotating or deleting a key follows the same rule: a key that manages keys can rotate or delete only keys whose access it also has. Listing raw events (GET /api/v1/events) requires project:events:read, which the read-only analytics preset leaves out because events carry data about individual end users. Connecting or disconnecting an ad account requires project:ads:manage, which the preset also leaves out.

A request that needs a permission the key lacks is answered with 403. Event capture rejects a scoped key without project:events:write as unauthorized.

User API keys

A user API key acts as a signed-in user. It is useful for local tools and automation that need access to more than one project. Send it in the x-api-key header:

curl https://api.voidhash.com/api/v1/auth/session \
  -H "x-api-key: $VOIDHASH_API_KEY"

The CLI obtains and stores this credential for you when you run voidhash-cli auth login.

Publishable keys

A publishable key is safe to ship inside an app. It only authorizes the device-facing SDK surface, and it must be paired with a customer identity in the x-distinct-id header:

curl https://api.voidhash.com/api/v1/sdk/person \
  -H "x-publishable-key: vh_pk_..." \
  -H "x-distinct-id: user_123"

The official SDKs also send platform and client metadata that these endpoints require. Prefer the SDK over calling them directly.

Distinct ids outside printable ASCII

HTTP header values are limited to printable ASCII. When a distinct id contains any other character, such as an accented letter or an emoji, send its UTF-8 bytes percent-encoded and add x-distinct-id-encoding: percent:

curl https://api.voidhash.com/api/v1/sdk/person \
  -H "x-publishable-key: vh_pk_..." \
  -H "x-distinct-id: Zo%C3%AB" \
  -H "x-distinct-id-encoding: percent"

Voidhash decodes the header only when that marker is present. Without it, the value is used exactly as sent, so an id that contains a literal % keeps its identity. Send printable ASCII ids as they are.

A distinct id is at most 255 characters and must not be blank or contain a NUL character. A missing, blank or malformed x-distinct-id is answered with 400 and an Api/SdkValidationError body, not 401. A 401 always means the publishable key itself was rejected.

Verify a credential

Call GET /api/v1/auth/session with any credential. The response shows how the key was resolved and which project it can access.

A valid key can still receive a 403 when it lacks permission for a specific operation.

Event capture

The event capture endpoints, /i/v1/capture and /i/v1/batch, accept either a secret key or a publishable key. Which one you send depends on where the request comes from.

From a backend, send the project secret key as x-secret-key. No x-distinct-id header is needed, because each event carries its own distinct_id.

From a distributed client that cannot hold a secret, send the publishable key as a token field in the JSON body instead.

Send one or the other. When both are present, the body token wins. See Event Capture for request examples.

PreviousAPI overviewNextList Ad Accounts

On this page

Project secret keysLimit what a secret key can doUser API keysPublishable keysDistinct ids outside printable ASCIIVerify a credentialEvent capture