This guide covers the changes to identity endpoints between v1 and v2. Both versions provide full identity management capabilities with different API patterns.

Overview

What Changed in v2:

  • HTTP methods: GET endpoints changed to POST for consistency
  • Request format: Query parameters moved to request body
  • Response format: Direct response wrapped in structured {meta, data} format
  • Parameter flexibility: Enhanced parameter handling (accepts both identityId and externalId)
  • Error handling: Improved error response structure

Migration Impact:

  • v1: Mixed GET/POST with query parameters and direct responses
  • v2: All POST with request bodies and structured {meta, data} responses
  • Benefit: Consistent API patterns, better error tracking, enhanced flexibility

POST /v1/identities.createIdentity → POST /v2/identities.createIdentity

Purpose: Create a new identity with metadata and rate limits. Changes: Request format unchanged, response wrapped in structured format.
v1 vs v2: Create Identity Request
// v1: POST /v1/identities.createIdentity
{
  "externalId": "user_123",
  "meta": {
    "email": "user@example.com",
    "plan": "pro"
  },
  "ratelimits": [
    {
      "name": "requests",
      "limit": 1000,
      "duration": 3600000
    }
  ]
}

// v2: POST /v2/identities.createIdentity (same request format)
{
  "externalId": "user_123",
  "meta": {
    "email": "user@example.com",
    "plan": "pro"
  },
  "ratelimits": [
    {
      "name": "requests",
      "limit": 1000,
      "duration": 3600000
    }
  ]
}

GET /v1/identities.getIdentity → POST /v2/identities.getIdentity

Purpose: Retrieve identity data by ID or external ID. Key Changes: GET with query parameters → POST with request body, response format enhanced.
v1 vs v2: Get Identity Request
# v1: GET with query parameters
curl -X GET "https://api.unkey.dev/v1/identities.getIdentity?externalId=user_123" \
  -H "Authorization: Bearer <your-root-key>"

# Alternative v1: Using identityId
curl -X GET "https://api.unkey.dev/v1/identities.getIdentity?identityId=identity_123" \
  -H "Authorization: Bearer <your-root-key>"

# v2: POST with request body (accepts both ID types)
curl -X POST https://api.unkey.com/v2/identities.getIdentity \
  -H "Authorization: Bearer <your-root-key>" \
  -H "Content-Type: application/json" \
  -d '{"identity": "user_123"}'

GET /v1/identities.listIdentities → POST /v2/identities.listIdentities

Purpose: Get paginated list of all identities. Key Changes: GET with query parameters → POST with request body, enhanced pagination structure.
v1 vs v2: List Identities Request
# v1: GET with query parameters
curl -X GET "https://api.unkey.dev/v1/identities.listIdentities?limit=50&cursor=eyJrZXkiOiJrZXlfMTIzNCJ9" \
  -H "Authorization: Bearer <your-root-key>"

# v2: POST with request body
curl -X POST https://api.unkey.com/v2/identities.listIdentities \
  -H "Authorization: Bearer <your-root-key>" \
  -H "Content-Type: application/json" \
  -d '{"limit": 50, "cursor": "eyJrZXkiOiJrZXlfMTIzNCJ9"}'

POST /v1/identities.updateIdentity → POST /v2/identities.updateIdentity

Purpose: Update identity metadata and rate limits. Changes: Enhanced parameter flexibility, structured response format.
v1 vs v2: Update Identity Request
// v1: Requires specific ID field
{
  "identityId": "id_abc123",  // or "externalId": "user_123"
  "meta": {
    "email": "user@example.com",
    "plan": "enterprise"
  },
  "ratelimits": [
    {
      "name": "requests",
      "limit": 5000,
      "duration": 3600000
    }
  ]
}

// v2: Flexible identity parameter
{
  "identity": "user_123",  // accepts both identityId or externalId
  "meta": {
    "email": "user@example.com",
    "plan": "enterprise"
  },
  "ratelimits": [
    {
      "name": "requests",
      "limit": 5000,
      "duration": 3600000
    }
  ]
}

POST /v1/identities.deleteIdentity → POST /v2/identities.deleteIdentity

Purpose: Permanently delete an identity. Changes: Enhanced parameter flexibility (v2 accepts both ID types), structured response.
v1 vs v2: Delete Identity Request
// v1: Requires identityId specifically
{
  "identityId": "id_abc123def456"
}

// v2: Flexible identity parameter
{
  "identity": "user_123"  // accepts both identityId or externalId
}