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.
Request Comparison
Response Comparison
cURL Examples
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
}
]
}
See all 31 lines
v1 vs v2: Create Identity Response
// v1: Direct response
{
"identityId" : "id_abc123def456"
}
// v2: Structured response with meta wrapper
{
"meta" : {
"requestId" : "req_createidentity123"
},
"data" : {
"identityId" : "id_abc123def456"
}
}
See all 14 lines
# v1: Create identity
curl -X POST https://api.unkey.dev/v1/identities.createIdentity \
-H "Authorization: Bearer <your-root-key>" \
-H "Content-Type: application/json" \
-d '{"externalId": "user_123", "meta": {"email": "user@example.com"}, "ratelimits": [{"name": "requests", "limit": 1000, "duration": 3600000}]}'
# v2: Create identity (same request, structured response)
curl -X POST https://api.unkey.com/v2/identities.createIdentity \
-H "Authorization: Bearer <your-root-key>" \
-H "Content-Type: application/json" \
-d '{"externalId": "user_123", "meta": {"email": "user@example.com"}, "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.
Request Migration
Response Comparison
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"}'
v1 vs v2: Get Identity Response
// v1: Direct response
{
"id" : "id_abc123def456" ,
"externalId" : "user_123" ,
"meta" : {
"email" : "user@example.com" ,
"plan" : "pro"
},
"ratelimits" : [
{
"name" : "requests" ,
"limit" : 1000 ,
"duration" : 3600000
}
]
}
// v2: Structured response with meta wrapper
{
"meta" : {
"requestId" : "req_getidentity456"
},
"data" : {
"id" : "id_abc123def456" ,
"externalId" : "user_123" ,
"meta" : {
"email" : "user@example.com" ,
"plan" : "pro"
},
"ratelimits" : [
{
"id" : "rl_abcdef123456" ,
"name" : "requests" ,
"limit" : 1000 ,
"duration" : 3600000
}
]
}
}
See all 39 lines
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.
Request Migration
Response Comparison
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"}'
v1 vs v2: List Identities Response
// v1: Direct response with total count
{
"identities" : [
{
"id" : "id_abc123" ,
"externalId" : "user_123" ,
"ratelimits" : [
{
"name" : "requests" ,
"limit" : 1000 ,
"duration" : 3600000
}
]
}
],
"cursor" : "eyJrZXkiOiJrZXlfMTIzNCJ9" ,
"total" : 42
}
// v2: Structured response with pagination object
{
"meta" : {
"requestId" : "req_listidentities789"
},
"data" : [
{
"id" : "id_abc123" ,
"externalId" : "user_123" ,
"meta" : {
"email" : "user@example.com" ,
"plan" : "pro"
},
"ratelimits" : [
{
"id" : "rl_abcdef123456" ,
"name" : "requests" ,
"limit" : 1000 ,
"duration" : 3600000
}
]
}
],
"pagination" : {
"cursor" : "eyJrZXkiOiJrZXlfMTIzNCJ9"
}
}
See all 46 lines
POST /v1/identities.updateIdentity → POST /v2/identities.updateIdentity
Purpose: Update identity metadata and rate limits.
Changes: Enhanced parameter flexibility, structured response format.
Request Comparison
Response Comparison
cURL Examples
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
}
]
}
See all 31 lines
v1 vs v2: Update Identity Response
// v1: Direct response
{
"id" : "id_abc123def456" ,
"externalId" : "user_123" ,
"meta" : {
"email" : "user@example.com" ,
"plan" : "enterprise"
},
"ratelimits" : [
{
"name" : "requests" ,
"limit" : 5000 ,
"duration" : 3600000
}
]
}
// v2: Structured response with meta wrapper
{
"meta" : {
"requestId" : "req_updateidentity789"
},
"data" : {
"id" : "id_abc123def456" ,
"externalId" : "user_123" ,
"meta" : {
"email" : "user@example.com" ,
"plan" : "enterprise"
},
"ratelimits" : [
{
"id" : "rl_abcdef123456" ,
"name" : "requests" ,
"limit" : 5000 ,
"duration" : 3600000
}
]
}
}
See all 39 lines
# v1: Update identity
curl -X POST https://api.unkey.dev/v1/identities.updateIdentity \
-H "Authorization: Bearer <your-root-key>" \
-H "Content-Type: application/json" \
-d '{"externalId": "user_123", "meta": {"plan": "enterprise"}, "ratelimits": [{"name": "requests", "limit": 5000, "duration": 3600000}]}'
# v2: Update identity (enhanced flexibility)
curl -X POST https://api.unkey.com/v2/identities.updateIdentity \
-H "Authorization: Bearer <your-root-key>" \
-H "Content-Type: application/json" \
-d '{"identity": "user_123", "meta": {"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.
Request Comparison
Response Comparison
cURL Examples
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
}
See all 9 lines
v1 vs v2: Delete Identity Response
// v1: Empty object response
{}
// v2: Structured response with meta wrapper
{
"meta" : {
"requestId" : "req_deleteidentity999"
}
}
See all 9 lines
# v1: Delete identity (requires identityId)
curl -X POST https://api.unkey.dev/v1/identities.deleteIdentity \
-H "Authorization: Bearer <your-root-key>" \
-H "Content-Type: application/json" \
-d '{"identityId": "id_abc123def456"}'
# v2: Delete identity (accepts externalId or identityId)
curl -X POST https://api.unkey.com/v2/identities.deleteIdentity \
-H "Authorization: Bearer <your-root-key>" \
-H "Content-Type: application/json" \
-d '{"identity": "user_123"}'
Last modified on February 16, 2026