Skip to main content

Tenant API

The Tenant API lets you create tenants (workspaces), retrieve tenant details, and rotate API keys. Each tenant is an isolated workspace with its own keys, quotas, and billing plan.


Create Tenant

POST/api/v1/tenantsCreate a new tenant workspace and receive an API key.

Creates a new tenant with the specified name and plan. Returns the tenant details.

Create an API key next

This endpoint creates the tenant only. To obtain an API key, call POST /api/v1/tenants/{tenant_id}/api-keys after creation. The API key is shown only once in that response — store it securely.

Request body

FieldTypeRequiredDescription
namestringYesA human-readable name for the tenant (1–255 characters).
planstringNoPricing plan: "free", "starter", "growth", "pro", or "enterprise". Defaults to "free".

Response (201 Created)

FieldTypeDescription
data.idstring (UUID)The unique tenant identifier.
data.namestringThe tenant name.
data.planstringThe selected plan.
data.statusstringTenant status, initially "active".
data.created_atstring (ISO 8601)When the tenant was created.
data.updated_atstring (ISO 8601)When the tenant was last updated.

Example

RequestPOST/api/v1/tenants
Content-Type: application/json
{
  "name": "Acme Corp",
  "plan": "starter"
}
Response201
{
  "data": {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "name": "Acme Corp",
    "plan": "starter",
    "status": "active",
    "created_at": "2026-01-15T10:00:00.000Z",
    "updated_at": "2026-01-15T10:00:00.000Z"
  },
  "request_id": "d0e1f2a3-b4c5-6789-0123-456789abcdef",
  "timestamp": "2026-01-15T10:00:00.000Z"
}
Create tenant
curl -X POST https://api.qpher.ai/api/v1/tenants \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Corp",
    "plan": "starter"
  }'

Errors

HTTP StatusError CodeDescription
400ERR_INVALID_001Invalid request body — missing name, invalid plan, or name too short/long.
409ERR_CONFLICT_001A tenant with this name already exists.

Create API Key

POST/api/v1/tenants/{id}/api-keysCreate a new API key for the tenant.

Creates a new API key. The plaintext key is returned only once in the response. Key quota is enforced per plan tier.

API key shown once

The api_key field is included only in this response. It is never returned again. Copy it immediately and store it in a secure location such as a secrets manager or encrypted vault.

Path parameters

ParameterTypeRequiredDescription
idstring (UUID)YesThe tenant ID.

Response (201 Created)

FieldTypeDescription
data.api_keystringThe plaintext API key. Shown only once.
data.key_last4stringLast 4 characters of the key (for display).
data.versionintegerKey version number.
data.statusstringKey status (always "active").
data.created_atstring (ISO 8601)When the key was created.

Example

RequestPOST/api/v1/tenants/f47ac10b-58cc-4372-a567-0e02b2c3d479/api-keys
Content-Type: application/json
Response201
{
  "data": {
    "api_key": "qph_live_abc123def456ghi789",
    "key_last4": "h789",
    "version": 1,
    "status": "active",
    "created_at": "2026-01-15T10:00:00.000Z"
  },
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "timestamp": "2026-01-15T10:00:00.000Z"
}

Errors

HTTP StatusError CodeDescription
400ERR_INVALID_001Key quota exceeded for the current plan.
401ERR_AUTH_001Missing or invalid API key.
404ERR_NOT_FOUND_001Tenant not found.
429ERR_RATE_LIMIT_001Rate limit exceeded — reduce request frequency or upgrade your plan.

List API Keys

GET/api/v1/tenants/{tenant_id}/api-keysList all API keys for a tenant (metadata only, no plaintext).

Returns all API keys for the specified tenant. The plaintext key is never returned — only metadata such as key_last4, version, and status.

Path parameters

ParameterTypeRequiredDescription
tenant_idstring (UUID)YesThe tenant ID.

Response (200 OK)

FieldTypeDescription
data.api_keysarrayArray of API key metadata objects.
data.api_keys[].key_last4stringLast 4 characters of the key (for display).
data.api_keys[].versionintegerKey version number.
data.api_keys[].statusstring"active" or "revoked".
data.api_keys[].created_atstring (ISO 8601)When the key was created.
data.api_keys[].revoked_atstring | nullWhen the key was revoked, or null if still active.
data.totalintegerTotal number of API keys.

Example

RequestGET/api/v1/tenants/f47ac10b-58cc-4372-a567-0e02b2c3d479/api-keys
X-API-Key: qph_your_key_here
Response200
{
  "data": {
    "api_keys": [
      {
        "key_last4": "h789",
        "version": 2,
        "status": "active",
        "created_at": "2026-02-01T12:00:00.000Z",
        "revoked_at": null
      },
      {
        "key_last4": "d456",
        "version": 1,
        "status": "revoked",
        "created_at": "2026-01-15T10:00:00.000Z",
        "revoked_at": "2026-02-01T12:00:00.000Z"
      }
    ],
    "total": 2
  },
  "request_id": "b2c3d4e5-f6a7-8901-2345-678901abcdef",
  "timestamp": "2026-02-01T12:05:00.000Z"
}

Errors

HTTP StatusError CodeDescription
401ERR_AUTH_001Missing or invalid API key.
404ERR_NOT_FOUND_001Tenant not found.

Get Tenant

GET/api/v1/tenants/{id}Retrieve details for a specific tenant.

Returns tenant details. The API key is not included in this response for security reasons.

Path parameters

ParameterTypeRequiredDescription
idstring (UUID)YesThe tenant ID.

Response (200 OK)

FieldTypeDescription
data.idstring (UUID)The tenant identifier.
data.namestringThe tenant name.
data.planstringThe current plan.
data.statusstringTenant status: "active", "suspended", etc.
data.created_atstring (ISO 8601)When the tenant was created.
data.updated_atstring (ISO 8601)When the tenant was last updated.

Example

RequestGET/api/v1/tenants/f47ac10b-58cc-4372-a567-0e02b2c3d479
X-API-Key: qph_your_key_here
Response200
{
  "data": {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "name": "Acme Corp",
    "plan": "starter",
    "status": "active",
    "created_at": "2026-01-15T10:00:00.000Z",
    "updated_at": "2026-01-15T10:00:00.000Z"
  },
  "request_id": "e1f2a3b4-c5d6-7890-1234-567890abcdef",
  "timestamp": "2026-01-15T10:05:00.000Z"
}
Get tenant
curl -X GET https://api.qpher.ai/api/v1/tenants/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
  -H "X-API-Key: qph_your_key_here"

Errors

HTTP StatusError CodeDescription
401ERR_AUTH_001Missing or invalid API key.
404ERR_NOT_FOUND_001Tenant not found.

Rotate API Key

POST/api/v1/tenants/{id}/api-keys/rotateRotate the API key for a tenant, revoking the old key.

Generates a new API key and immediately revokes the old one. There is a brief concurrent window where both keys are valid to allow for zero-downtime rotation.

API key shown once

The new api_key inside data.new_key is included only in this response. Store it immediately. The old key will stop working shortly after rotation.

Path parameters

ParameterTypeRequiredDescription
idstring (UUID)YesThe tenant ID.

Response (200 OK)

FieldTypeDescription
data.new_key.api_keystringThe new API key. Shown only once.
data.new_key.key_last4stringLast 4 characters of the new key (for display).
data.new_key.versionintegerVersion number of the new key.
data.new_key.statusstringKey status (always "active").
data.new_key.created_atstring (ISO 8601)When the new key was created.
data.revoked_versioninteger | nullVersion of the revoked key, or null if none.

Example

RequestPOST/api/v1/tenants/f47ac10b-58cc-4372-a567-0e02b2c3d479/api-keys/rotate
X-API-Key: qph_your_key_here
Content-Type: application/json
Response200
{
  "data": {
    "new_key": {
      "api_key": "qph_new_rotated_key_here",
      "key_last4": "here",
      "version": 2,
      "status": "active",
      "created_at": "2026-02-01T12:00:00.000Z"
    },
    "revoked_version": 1
  },
  "request_id": "f2a3b4c5-d6e7-8901-2345-678901abcdef"
}
Rotate API key
curl -X POST https://api.qpher.ai/api/v1/tenants/f47ac10b-58cc-4372-a567-0e02b2c3d479/api-keys/rotate \
  -H "X-API-Key: qph_your_key_here" \
  -H "Content-Type: application/json"

Errors

HTTP StatusError CodeDescription
401ERR_AUTH_001Missing or invalid API key.
404ERR_NOT_FOUND_001Tenant not found.
429ERR_RATE_LIMIT_001Rate limit exceeded — reduce request frequency or upgrade your plan.

Revoke API Key

DELETE/api/v1/tenants/{tenant_id}/api-keys/{version}Revoke a specific API key by version number.

Revokes an API key immediately. The key stops working as soon as it is revoked.

Irreversible operation

Revoking an API key is permanent. The key cannot be reactivated. If you need a new key, use POST /api/v1/tenants/{tenant_id}/api-keys to create one.

Path parameters

ParameterTypeRequiredDescription
tenant_idstring (UUID)YesThe tenant ID.
versionintegerYesThe API key version to revoke.

Response (200 OK)

FieldTypeDescription
data.key_last4stringLast 4 characters of the revoked key.
data.versionintegerThe revoked key version.
data.statusstring"revoked".
data.created_atstring (ISO 8601)When the key was originally created.
data.revoked_atstring (ISO 8601)When the key was revoked.

Example

RequestDELETE/api/v1/tenants/f47ac10b-58cc-4372-a567-0e02b2c3d479/api-keys/1
X-API-Key: qph_your_key_here
Response200
{
  "data": {
    "key_last4": "d456",
    "version": 1,
    "status": "revoked",
    "created_at": "2026-01-15T10:00:00.000Z",
    "revoked_at": "2026-03-01T08:00:00.000Z"
  },
  "request_id": "c3d4e5f6-a7b8-9012-3456-789012abcdef",
  "timestamp": "2026-03-01T08:00:00.000Z"
}

Errors

HTTP StatusError CodeDescription
401ERR_AUTH_001Missing or invalid API key.
404ERR_NOT_FOUND_001Tenant or API key version not found.

Plan Tiers

PlanMonthly PriceRequests/minPQC Keys
Free$01002
Starter$9950010
Growth$1791,00025
Pro$2995,000100
EnterpriseFrom $999CustomUnlimited
Upgrading your plan

To change your plan, use the Qpher Portal at portal.qpher.ai or contact sales for Enterprise pricing.