Authentication
Authenticate with Voisnap using API keys or JWT tokens. Includes MFA (TOTP + FIDO2) and all auth endpoints.
Authentication
Voisnap supports two authentication methods:
- API Keys — for server-to-server integrations and SDK usage (recommended)
- JWT (JSON Web Tokens) — for user-facing applications, the Console, and short-lived sessions
API Keys
API keys are the primary authentication mechanism for programmatic access to the Voisnap API.
Key format
All API keys follow the format vsnp_<env>_<random>:
vsnp_live_k8za1b2c3d4e5f6g7h8i9j0 # Production
vsnp_sb_k8za1b2c3d4e5f6g7h8i9j0 # Sandbox
Available scopes
| Scope | Description |
|---|---|
agents:read | List and retrieve agents and their configuration |
agents:write | Create, update, activate, and delete agents |
conversations:read | List and retrieve conversations, transcripts, and analysis |
conversations:write | Delete conversations, add tags, update outcomes |
telephony:read | List numbers, SIP trunks, and usage stats |
telephony:write | Provision/release numbers, create SIP trunks, assign numbers |
webhooks:read | List and retrieve webhook configurations |
webhooks:write | Create, update, and delete webhook configurations |
analytics:read | Access analytics dashboards and export reports |
billing:read | View invoices, usage, and subscription details |
:::tip
Follow the principle of least privilege. A key used only to read conversations only needs conversations:read — not write access to agents.
:::
Create an API key
curl -X POST https://api.voisnap.ai/api/v1/api-keys \
-H "Authorization: Bearer vsnp_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Production backend",
"scopes": ["agents:read", "conversations:read", "webhooks:write"],
"expiresAt": "2026-12-31T23:59:59Z"
}'
key = client.api_keys.create(
name="Production backend",
scopes=["agents:read", "conversations:read", "webhooks:write"],
expires_at="2026-12-31T23:59:59Z"
)
const key = await client.apiKeys.create({
name: 'Production backend',
scopes: ['agents:read', 'conversations:read', 'webhooks:write'],
expiresAt: '2026-12-31T23:59:59Z',
});
List API keys
curl https://api.voisnap.ai/api/v1/api-keys \
-H "Authorization: Bearer vsnp_live_..."
Response:
{
"data": [
{
"id": "key_01HXK8ZABCDEF",
"name": "Production backend",
"keyPrefix": "vsnp_live_k8z",
"scopes": ["agents:read", "conversations:read", "webhooks:write"],
"createdAt": "2025-06-15T10:00:00Z",
"lastUsedAt": "2025-06-16T14:22:00Z",
"expiresAt": "2026-12-31T23:59:59Z"
}
],
"page": 1,
"pageSize": 20,
"total": 1,
"totalPages": 1
}
Revoke an API key
curl -X DELETE https://api.voisnap.ai/api/v1/api-keys/key_01HXK8ZABCDEF \
-H "Authorization: Bearer vsnp_live_..."
Using an API key
Pass the key in the Authorization header as a Bearer token:
curl https://api.voisnap.ai/api/v1/agents \
-H "Authorization: Bearer vsnp_live_k8za1b2c3d4e5f6g7h8i9j0"
import voisnap
client = voisnap.VoisnapClient(api_key="vsnp_live_k8za1b2c3d4e5f6g7h8i9j0")
import { VoisnapClient } from '@voisnap/sdk';
const client = new VoisnapClient({ apiKey: 'vsnp_live_k8za1b2c3d4e5f6g7h8i9j0' });
JWT Authentication
JWT authentication is used for interactive sessions (e.g., the Console, custom admin portals). Access tokens expire after 15 minutes and can be refreshed.
Login
POST https://api.voisnap.ai/api/v1/auth/login
Content-Type: application/json
{
"email": "you@example.com",
"password": "your-password"
}
Response (no MFA):
{
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "rt_01HXK9MNPQ...",
"tokenType": "Bearer",
"expiresIn": 900,
"mfaRequired": false
}
Response (MFA required):
{
"mfaRequired": true,
"mfaToken": "mfa_01HXDEF...",
"mfaMethods": ["totp", "fido2"],
"accessToken": null,
"refreshToken": null
}
Multi-Factor Authentication (MFA)
Voisnap supports TOTP (authenticator apps) and FIDO2 (passkeys/hardware security keys).
TOTP verification
POST https://api.voisnap.ai/api/v1/auth/mfa/verify
Content-Type: application/json
{
"mfaToken": "mfa_01HXDEF...",
"method": "totp",
"code": "482910"
}
FIDO2 / WebAuthn verification
# 1. Get challenge
POST https://api.voisnap.ai/api/v1/auth/mfa/fido2/challenge
Content-Type: application/json
{
"mfaToken": "mfa_01HXDEF..."
}
# Response:
# {
# "challenge": "base64url-encoded-challenge",
# "rpId": "voisnap.ai",
# "userVerification": "preferred"
# }
# 2. Submit assertion
POST https://api.voisnap.ai/api/v1/auth/mfa/fido2/verify
Content-Type: application/json
{
"mfaToken": "mfa_01HXDEF...",
"credentialId": "base64url...",
"authenticatorData": "base64url...",
"clientDataJSON": "base64url...",
"signature": "base64url..."
}
Both MFA methods return the same full token response on success:
{
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "rt_01HXK9MNPQ...",
"tokenType": "Bearer",
"expiresIn": 900,
"mfaRequired": false
}
Refresh access token
Access tokens expire in 900 seconds (15 minutes). Refresh them using the refresh token:
POST https://api.voisnap.ai/api/v1/auth/refresh
Content-Type: application/json
{
"refreshToken": "rt_01HXK9MNPQ..."
}
Response:
{
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...(new token)",
"refreshToken": "rt_01HXK9NEW...",
"tokenType": "Bearer",
"expiresIn": 900
}
:::note Refresh tokens are single-use (rotation). Each refresh returns a new refresh token; the old one is immediately revoked. :::
Logout
POST https://api.voisnap.ai/api/v1/auth/logout
Authorization: Bearer <access_token>
Content-Type: application/json
{
"refreshToken": "rt_01HXK9MNPQ..."
}
Using a JWT
curl https://api.voisnap.ai/api/v1/agents \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
# JWT client — provide access_token directly
client = voisnap.VoisnapClient(access_token="eyJhbGci...")
# Or use the built-in auth helper
auth = voisnap.Auth(base_url="https://api.voisnap.ai")
tokens = auth.login(email="you@example.com", password="your-password")
client = voisnap.VoisnapClient(access_token=tokens.access_token)
Auth endpoints summary
| Method | Endpoint | Description |
|---|---|---|
POST | /api/v1/auth/login | Authenticate with email + password |
POST | /api/v1/auth/refresh | Exchange refresh token for new access token |
POST | /api/v1/auth/logout | Revoke refresh token and end session |
POST | /api/v1/auth/mfa/verify | Complete TOTP MFA challenge |
POST | /api/v1/auth/mfa/fido2/challenge | Get FIDO2 assertion challenge |
POST | /api/v1/auth/mfa/fido2/verify | Complete FIDO2 MFA challenge |
GET | /api/v1/api-keys | List API keys |
POST | /api/v1/api-keys | Create API key |
GET | /api/v1/api-keys/{id} | Get API key details |
DELETE | /api/v1/api-keys/{id} | Revoke API key |