API Key Authentication
API keys are long-lived credentials you can embed directly into applications, mobile clients, server-side integrations, and automation workflows — without exposing your account password. Each key can be named, scoped to specific operations, restricted by report type or IP address, and disabled at any time without affecting other keys or your account login.
The workflow is two steps: exchange your API key for a short-lived JWT access token, then use that token exactly as you would with password-based login. The API key itself is never sent to report endpoints — only the JWT.
Why Use API Keys?
| Scenario | Why API keys help |
|---|---|
| Mobile or desktop app | Embed the key in the app binary. If it leaks, revoke just that key — your account and other integrations remain untouched. |
| Server-side integration | Give each service its own key. Rotate or revoke per-service without coordinating across all consumers. |
| Multiple team members | Issue one key per developer or environment (dev, staging, production). Revoke access for a departed team member without changing shared credentials. |
| Scoped access | Restrict a key to specific report types (e.g. BASIC only) so a key compromise cannot trigger higher-cost reports. |
| IP-locked automation | Bind a key to specific IP addresses — requests from any other origin are rejected even if the key is valid. |
API Key Format
All VinLink API keys follow this format:
vk_{publicId}_{secret}
The publicId is a short identifier used for management (list, revoke, rotate) and is safe to log. The secret portion is shown only once at creation and cannot be recovered — store it securely immediately.
Step 1 — Create an API Key
API key creation requires your account JWT (obtained via password login). Log in first, then issue the creation request:
# Log in with your account credentials
TOKEN=$(curl -s -X POST https://api.vinlink.com/user/login \
-H "Content-Type: application/json" \
-d '{"login":"your@email.com","password":"yourpassword"}' \
| python3 -c "import sys,json; print(json.load(sys.stdin)['accessToken'])")
# Create a new API key
curl -X POST https://api.vinlink.com/user/api-keys \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "My Mobile App",
"description": "iOS client — production",
"scopes": ["REPORT"],
"reportTypes": ["BASIC", "BASIC_PLUS"],
"expiresAt": null,
"ipWhitelist": null
}'
Request Fields
| Field | Required | Description |
|---|---|---|
name | Yes | Human-readable label (max 100 chars) |
description | No | Optional notes about the key’s purpose (max 500 chars) |
scopes | Yes | At least one scope — use ["REPORT"] for report access |
reportTypes | No | Restrict to specific report types (e.g. ["BASIC","RECALL"]). Omit or leave empty for no restriction. |
expiresAt | No | ISO 8601 timestamp for automatic expiry. Omit or null for no expiry. |
ipWhitelist | No | Comma-separated IP addresses or CIDR blocks. Omit or null to allow any IP. |
Response — Save the Key Immediately
The fullApiKey field is returned only once. It cannot be retrieved again after this response. Copy it to a secure location before discarding the response.
{
"publicId": "a1b2c3d4",
"fullApiKey": "vk_a1b2c3d4_s3cr3tpart",
"name": "My Mobile App",
"description": "iOS client — production",
"scopes": ["REPORT"],
"reportTypes": ["BASIC", "BASIC_PLUS"],
"status": "ACTIVE",
"createdAt": "2025-06-01T12:00:00Z",
"expiresAt": null,
"ipWhitelist": null
}
Security note: Only the
publicIdis stored on our servers. The secret is hashed immediately after creation. If you lose the key, revoke it and create a new one.
Step 2 — Exchange the API Key for a JWT
Use POST /auth/api-key/token to exchange your API key for a standard JWT access/refresh token pair. Three delivery methods are supported — choose the one that fits your client:
Option A — Authorization Header (recommended)
curl -X POST https://api.vinlink.com/auth/api-key/token \
-H "Authorization: ApiKey vk_a1b2c3d4_s3cr3tpart"
Option B — Query Parameter (GET)
curl "https://api.vinlink.com/auth/api-key/token?apiKey=vk_a1b2c3d4_s3cr3tpart"
Option C — Request Body (POST)
curl -X POST https://api.vinlink.com/auth/api-key/token \
-H "Content-Type: application/json" \
-d '{"apiKey": "vk_a1b2c3d4_s3cr3tpart"}'
Response
The response is identical to a password login — an accessToken, refreshToken, and expiry information:
{
"accessToken": "eyJhbGci...",
"refreshToken": "eyJhbGci...",
"tokenType": "Bearer",
"expiresIn": 3600
}
Step 3 — Call the API
Use the access token exactly as with password-based auth:
# Full end-to-end: exchange key, then call a report endpoint
TOKEN=$(curl -s -X POST https://api.vinlink.com/auth/api-key/token \
-H "Authorization: ApiKey vk_a1b2c3d4_s3cr3tpart" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['accessToken'])")
curl "https://api.vinlink.com/report/v1/report/BASIC?vin=1HGBH41JXMN109186" \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json"
When the access token expires, use the refreshToken to obtain a new pair — no need to re-present the API key:
curl -X POST https://api.vinlink.com/auth/refresh \
-H "Content-Type: application/json" \
-d '{"refreshToken": "eyJhbGci..."}'
Managing Your API Keys
All management endpoints require your account JWT (from password login). The API key itself cannot be used to manage keys.
List Keys
# Active keys only (default)
curl https://api.vinlink.com/user/api-keys \
-H "Authorization: Bearer $TOKEN"
# Include revoked keys
curl "https://api.vinlink.com/user/api-keys?includeRevoked=true" \
-H "Authorization: Bearer $TOKEN"
Listing never returns the secret — only the publicId, name, status, scopes, and usage metadata (lastUsedAt).
Revoke a Key
Revocation is immediate and permanent. A revoked key cannot be re-activated.
curl -X DELETE https://api.vinlink.com/user/api-keys/{publicId} \
-H "Authorization: Bearer $TOKEN"
Alternatively, use a POST body if your HTTP client does not support DELETE with a body:
curl -X POST https://api.vinlink.com/user/api-keys/revoke \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"publicId": "a1b2c3d4"}'
Rotate a Key Secret
Rotation generates a new secret for an existing key, invalidating the old secret immediately. The publicId stays the same. Use this for periodic credential hygiene without recreating the key and updating all your scopes/settings.
curl -X POST https://api.vinlink.com/user/api-keys/{publicId}/rotate \
-H "Authorization: Bearer $TOKEN"
The response contains the new fullApiKey — again shown only once.
HTTP Status Codes
| Code | Meaning |
|---|---|
200 | Success |
201 | API key created |
400 | Missing or malformed API key / invalid request |
401 | Invalid, expired, or revoked API key |
404 | Key not found or not owned by your account |
Full API Reference
Interactive schemas for all API key endpoints are available in the Swagger UI under the API Key Authentication and API Key Management groups:
https://api.vinlink.com/swagger-ui/index.html
Support
For questions or to request access, contact us at administration@vinlink.com or use the contact form on our website.