Skip to content

Authentication & API Keys

Every 3PI partner authenticates using scoped API keys. Keys are designed for security-first integration with granular controls over what each key can access.


Key format

All 3PI partner keys use the vp3_ prefix for easy identification:

vp3_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4
  • Prefix: vp3_ — identifies this as a 3PI partner key
  • Length: 52 characters total (4-char prefix + 48 random characters)
  • Storage: SHA-256 hashed at rest — Vellocity never stores the plaintext

Using your key

Include the key in the Authorization header as a Bearer token:

curl https://api.vell.ai/api/v1/3pi-partners \
  -H "Authorization: Bearer vp3_YOUR_KEY_HERE" \
  -H "Accept: application/json"

Never expose keys client-side

Partner API keys should only be used in server-to-server communication. Never embed them in frontend code, mobile apps, or any client-accessible location.


Creating keys

Each partner can have multiple API keys for different environments or services.

curl -X POST https://api.vell.ai/api/v1/3pi-partners/42/keys \
  -H "Authorization: Bearer $ADMIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production - Content Service",
    "scoped_capabilities": ["ai_writer", "content_studio", "marketplace_seo"],
    "allowed_ip_addresses": ["203.0.113.10", "203.0.113.11"],
    "rate_limit_per_minute": 120,
    "daily_credit_limit": 5000,
    "expires_at": "2027-03-15T00:00:00Z"
  }'

Response:

{
  "data": {
    "id": 7,
    "name": "Production - Content Service",
    "prefix": "vp3_x9y8z7w6",
    "scoped_capabilities": ["ai_writer", "content_studio", "marketplace_seo"],
    "allowed_ip_addresses": ["203.0.113.10", "203.0.113.11"],
    "rate_limit_per_minute": 120,
    "daily_credit_limit": 5000,
    "is_active": true,
    "is_valid": true,
    "expires_at": "2027-03-15T00:00:00Z",
    "created_at": "2026-03-15T10:30:00Z"
  },
  "plaintext": "vp3_x9y8z7w6...",
  "warning": "Store this key securely. It will not be shown again."
}

Key parameters

Parameter Type Required Description
name string Yes Human-readable label for the key
scoped_capabilities string[] No Restrict to specific capabilities. null = inherit all from partner
allowed_ip_addresses string[] No IP allowlist. null = allow all IPs
rate_limit_per_minute integer No Max requests per minute (default: 60, max: 10,000)
daily_credit_limit integer No Max credits per day. null = unlimited
expires_at datetime No Auto-expire date. null = no expiration

Capability scoping

Keys can be restricted to specific capabilities. When scoped_capabilities is null, the key inherits all capabilities assigned to the partner.

{
  "scoped_capabilities": [
    "ai_writer",
    "marketplace_seo",
    "cosell_matching"
  ]
}

If a request targets a capability not in the key's scope, the API returns 403 Forbidden:

{
  "success": false,
  "error": {
    "code": "CAPABILITY_NOT_ALLOWED",
    "message": "This API key does not have access to the 'partner_central' capability"
  }
}

See Capabilities Reference for the full list of capability slugs.


IP allowlisting

Restrict key usage to specific IP addresses for defense-in-depth:

{
  "allowed_ip_addresses": ["203.0.113.10", "203.0.113.11"]
}

Requests from non-listed IPs receive 403 Forbidden. Set to null to allow any IP.


Rate limits

Each key has an independent rate limit:

Parameter Default Max
rate_limit_per_minute 60 10,000

When rate limited, the API returns 429 Too Many Requests with retry headers:

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1710500460
Retry-After: 15

Daily credit limits

Set a daily credit cap to control spend:

{
  "daily_credit_limit": 5000
}

When the limit is reached, subsequent requests return 429 with:

{
  "success": false,
  "error": {
    "code": "DAILY_CREDIT_LIMIT_EXCEEDED",
    "message": "This API key has consumed 5000/5000 credits today. Limit resets at midnight UTC."
  }
}

Sandbox requests don't count

Credit limits only apply to production requests. Sandbox mode requests always succeed regardless of limits.


Key rotation

Rotate a key to generate a new one with identical settings while revoking the old key:

curl -X POST https://api.vell.ai/api/v1/3pi-partners/42/keys/7/rotate \
  -H "Authorization: Bearer $ADMIN_API_KEY"

Response:

{
  "data": {
    "id": 8,
    "name": "Production - Content Service",
    "prefix": "vp3_n3w0k3y1",
    "scoped_capabilities": ["ai_writer", "content_studio", "marketplace_seo"],
    "rate_limit_per_minute": 120,
    "is_active": true,
    "created_at": "2026-03-15T14:00:00Z"
  },
  "plaintext": "vp3_n3w0k3y1...",
  "warning": "Store this key securely. It will not be shown again.",
  "revoked_key_id": 7
}

The old key is immediately revoked. Plan for a brief switchover window in your deployment.


Key revocation

Revoke a key to permanently disable it:

curl -X POST https://api.vell.ai/api/v1/3pi-partners/42/keys/7/revoke \
  -H "Authorization: Bearer $ADMIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason": "Compromised key"}'

Revoked keys cannot be re-activated. Create a new key instead.


Listing keys

View all keys for a partner:

curl https://api.vell.ai/api/v1/3pi-partners/42/keys \
  -H "Authorization: Bearer $ADMIN_API_KEY"

Response:

{
  "data": [
    {
      "id": 8,
      "name": "Production - Content Service",
      "prefix": "vp3_n3w0k3y1",
      "is_active": true,
      "is_valid": true,
      "total_requests": 1247,
      "last_used_at": "2026-03-15T13:45:00Z",
      "created_at": "2026-03-15T14:00:00Z"
    },
    {
      "id": 7,
      "name": "Production - Content Service",
      "prefix": "vp3_x9y8z7w6",
      "is_active": false,
      "is_valid": false,
      "revoked_at": "2026-03-15T14:00:00Z",
      "revoked_reason": "Key rotation",
      "total_requests": 8432,
      "created_at": "2026-03-15T10:30:00Z"
    }
  ]
}

Security best practices

  1. Use capability scoping — Only grant the capabilities each key needs
  2. Set IP allowlists — Restrict keys to known server IPs
  3. Set expiration dates — Auto-expire keys on a regular rotation schedule
  4. Use daily credit limits — Cap spend per key to limit blast radius
  5. Rotate regularly — Use the /rotate endpoint for zero-downtime key rotation
  6. Monitor usage — Review the Usage & Billing dashboard for anomalies
  7. One key per service — Issue separate keys for each service or environment
  8. Never log plaintext keys — The key hash, prefix, and ID are sufficient for debugging