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?

ScenarioWhy API keys help
Mobile or desktop appEmbed the key in the app binary. If it leaks, revoke just that key — your account and other integrations remain untouched.
Server-side integrationGive each service its own key. Rotate or revoke per-service without coordinating across all consumers.
Multiple team membersIssue one key per developer or environment (dev, staging, production). Revoke access for a departed team member without changing shared credentials.
Scoped accessRestrict a key to specific report types (e.g. BASIC only) so a key compromise cannot trigger higher-cost reports.
IP-locked automationBind 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

FieldRequiredDescription
nameYesHuman-readable label (max 100 chars)
descriptionNoOptional notes about the key’s purpose (max 500 chars)
scopesYesAt least one scope — use ["REPORT"] for report access
reportTypesNoRestrict to specific report types (e.g. ["BASIC","RECALL"]). Omit or leave empty for no restriction.
expiresAtNoISO 8601 timestamp for automatic expiry. Omit or null for no expiry.
ipWhitelistNoComma-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 publicId is 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

CodeMeaning
200Success
201API key created
400Missing or malformed API key / invalid request
401Invalid, expired, or revoked API key
404Key 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.