Unkey

API Design Overview

Our philosophy for building developer-friendly APIs

API Design Philosophy

At Unkey, we've designed our API with a focus on developer experience, consistency, and clarity. This document outlines our core design decisions and how you can best work with our API.

Core Principles

  • Clear Communication: Structured responses make success and failure equally informative
  • Practical Over Purist: We make pragmatic choices rather than rigidly adhering to any single paradigm
  • Predictable Patterns: Once you learn one endpoint, you'll understand them all

Response Structure

All API responses follow a consistent structure, making them predictable and easy to parse:

{
  "meta": {
    "requestId": "req_abc123xyz789"
  },
  "data": {
    // Operation-specific response data
  }
}

For paginated responses, we include a pagination object:

{
  "meta": {
    "requestId": "req_abc123xyz789",
    "timestamp": "2023-11-08T15:22:30Z"
  },
  "data": [
    // Array of items
  ],
  "pagination": {
    "cursor": "cursor_xyz123",
    "hasMore": true
  }
}

Working with the API

Always Use the Request ID

Every response includes a unique requestId in the metadata. When seeking support or debugging issues, always include this ID as it allows us to trace exactly what happened with your request.

You can also search for the requestId yourself in the logs.

Handling Pagination

For endpoints that return lists of items:

  1. Make your initial request
  2. Check for pagination.hasMore to see if more items exist
  3. If true, use the pagination.cursor value in your next request

Example:

// First request
const response = await fetch('https://api.unkey.com/v2/keys.listKeys', {
  method: 'POST',
  headers: { Authorization: `Bearer ${rootKey}` },
  body: JSON.stringify({ apiId: 'api_123' })
});
 
// Follow-up request with cursor
if (response.pagination?.hasMore) {
  const nextPage = await fetch('https://api.unkey.com/v2/keys.listKeys', {
    method: 'POST',
    headers: { Authorization: `Bearer ${rootKey}` },
    body: JSON.stringify({
      apiId: 'api_123',
      cursor: response.pagination.cursor
    })
  });
}

Versioning

Our API uses a major version in the URL (e.g., /v2/) and maintains backwards compatibility within each major version. When we need to make breaking changes, we increment the major version number.

We communicate deprecations well in advance, giving you time to update your integration before endpoints are removed.

On this page