Skip to content

API Reference

The TenantScale REST API provides programmatic access to tenants, API keys, subscriptions, webhooks, analytics, and more. Use it to integrate TenantScale into your existing backend, build custom dashboards, or automate tenant management.

Base URL

https://api.tenantscale.com/v1

For self-hosted deployments, replace api.tenantscale.com with your own domain:

https://tenantscale.yourcompany.com/v1

Authentication

All API requests must include an API key in the Authorization header:

Authorization: Bearer tsk_live_abc123def456

API keys are generated per tenant using the CLI or the Create API Key endpoint. API keys start with tsk_ followed by a prefix.

API Key Types

TypePrefixUse Case
Livetsk_live_Production API access
Testtsk_test_Development and testing

Authentication Errors

CodeStatusMeaning
INVALID_API_KEY401API key is missing, malformed, revoked, or expired
INSUFFICIENT_SCOPE403API key does not have the required scope

Success Responses

All successful responses follow a consistent shape:

json
{
  "data": { ... },
  "meta": {
    "requestId": "req_abc123"
  }
}

For list endpoints, the response includes pagination metadata:

json
{
  "data": [ ... ],
  "meta": {
    "requestId": "req_abc123",
    "page": 1,
    "limit": 20,
    "total": 142,
    "totalPages": 8
  }
}

Error Responses

Errors follow a consistent shape:

json
{
  "error": {
    "code": "INVALID_API_KEY",
    "message": "The provided API key is invalid or has been revoked.",
    "details": {
      "keyPrefix": "tsk_live_abc"
    }
  },
  "meta": {
    "requestId": "req_def456"
  }
}

Error Codes

CodeHTTP StatusDescription
INVALID_API_KEY401API key is missing, malformed, revoked, or expired
INSUFFICIENT_SCOPE403API key lacks required scope(s)
PLAN_LIMIT_EXCEEDED403Usage exceeds the tenant's plan limit
PLAN_FEATURE_MISSING403The tenant's plan does not include the required feature
RATE_LIMIT_EXCEEDED429Request rate exceeds allowed limit
NOT_FOUND404Requested resource does not exist
VALIDATION_ERROR422Request body failed validation
CONFLICT409Resource already exists (e.g., duplicate slug)
INTERNAL_ERROR500Unexpected server error
SERVICE_UNAVAILABLE503Temporary service disruption

Error Details

The details object provides additional context:

  • details.requiredScopes — For INSUFFICIENT_SCOPE: the scopes that were required
  • details.limit and details.usage — For PLAN_LIMIT_EXCEEDED: the limit that was exceeded and current usage
  • details.retryAfter — For RATE_LIMIT_EXCEEDED: seconds until the rate limit resets
  • details.field — For VALIDATION_ERROR: the field that failed validation
  • details.requiredFeature — For PLAN_FEATURE_MISSING: the feature that was required

Pagination

All list endpoints use cursor-based pagination with standard query parameters.

Query Parameters

ParameterTypeDefaultDescription
pageinteger1Page number (1-indexed)
limitinteger20Items per page (max: 100)

Response Fields

FieldTypeDescription
pageintegerCurrent page number
limitintegerItems per page
totalintegerTotal items across all pages
totalPagesintegerTotal number of pages

Pagination Example

GET /v1/tenants?page=2&limit=10
json
{
  "data": [ ... ],
  "meta": {
    "requestId": "req_789",
    "page": 2,
    "limit": 10,
    "total": 53,
    "totalPages": 6
  }
}

API Rate Limits

The TenantScale API enforces rate limits per API key and per IP address.

LimitValueApplies To
Requests per day per API key10,000 (configurable)All authenticated requests
Requests per minute per IP100Unauthenticated requests
Burst50 requests per secondAll requests

Rate limit headers are included in every response:

X-RateLimit-Limit: 10000
X-RateLimit-Remaining: 9942
X-RateLimit-Reset: 1625097600

Endpoints

Tenants

MethodPathDescriptionScopes
GET/tenantsList all tenantstenants:read
POST/tenantsCreate a new tenanttenants:write
GET/tenants/:idGet tenant detailstenants:read
PUT/tenants/:idUpdate tenanttenants:write
DELETE/tenants/:idDelete a tenanttenants:admin

POST /tenants

json
{
  "name": "Acme Corp",
  "slug": "acme-corp",
  "planId": "pro",
  "metadata": {
    "industry": "technology"
  }
}

API Keys

MethodPathDescriptionScopes
GET/tenants/:id/api-keysList API keys for a tenantapi-keys:read
POST/tenants/:id/api-keysCreate an API keyapi-keys:write
GET/api-keys/:keyIdGet API key detailsapi-keys:read
DELETE/api-keys/:keyIdRevoke an API keyapi-keys:write

POST /tenants/:id/api-keys

json
{
  "name": "Production Key",
  "scopes": ["tenants:read", "webhooks:write"],
  "expiresAt": "2025-12-31T23:59:59Z"
}

Plans

MethodPathDescriptionScopes
GET/plansList all plansplans:read
POST/plansCreate a new planplans:write
GET/plans/:idGet plan detailsplans:read
PUT/plans/:idUpdate a planplans:write
DELETE/plans/:idDelete a planplans:admin

Subscriptions

MethodPathDescriptionScopes
GET/tenants/:id/subscriptionGet subscription detailsbilling:read
POST/tenants/:id/subscriptionCreate or update subscriptionbilling:write
DELETE/tenants/:id/subscriptionCancel subscriptionbilling:write
POST/tenants/:id/subscription/portalCreate Stripe portal sessionbilling:write

Webhooks

MethodPathDescriptionScopes
GET/tenants/:id/webhooksList webhook endpointswebhooks:read
POST/tenants/:id/webhooksRegister a webhook endpointwebhooks:write
PUT/webhooks/:webhookIdUpdate webhook endpointwebhooks:write
DELETE/webhooks/:webhookIdDelete webhook endpointwebhooks:write
GET/webhooks/:webhookId/deliveriesList webhook delivery attemptswebhooks:read
POST/webhooks/:webhookId/redeliverRedeliver a webhookwebhooks:write

Audit Logs

MethodPathDescriptionScopes
GET/tenants/:id/audit-logsList audit log entriesaudit:read
POST/tenants/:id/audit-logsCreate an audit log entryaudit:write
GET/tenants/:id/audit-logs/statsAudit log statisticsaudit:read
DELETE/tenants/:id/audit-logs/purgePurge audit logsaudit:admin

Rate Limits

MethodPathDescriptionScopes
GET/tenants/:id/rate-limitsGet rate limit statusrate-limits:read
POST/tenants/:id/rate-limits/resetReset rate limit countersrate-limits:write

Analytics

MethodPathDescriptionScopes
GET/tenants/:id/analytics/overviewDashboard overviewanalytics:read
GET/tenants/:id/analytics/requestsRequest analytics by timeanalytics:read
GET/tenants/:id/analytics/errorsError analyticsanalytics:read

Billing

MethodPathDescriptionScopes
GET/tenants/:id/invoicesList invoicesbilling:read
GET/tenants/:id/invoices/:invoiceIdGet invoice detailsbilling:read
POST/tenants/:id/checkoutCreate Stripe checkout sessionbilling:write
POST/tenants/:id/portalCreate Stripe customer portal sessionbilling:write

System

MethodPathDescriptionScopes
GET/healthHealth checkNone (public)
GET/metricsPrometheus metricssystem:read
POST/stripe/webhookStripe webhook receiverNone (public, verified by signature)
POST/stripe/sync-plansSync plans to Stripesystem:write

Full Endpoint Summary

#MethodPathResource Group
1GET/tenantsTenants
2POST/tenantsTenants
3GET/tenants/:idTenants
4PUT/tenants/:idTenants
5DELETE/tenants/:idTenants
6GET/tenants/:id/api-keysAPI Keys
7POST/tenants/:id/api-keysAPI Keys
8GET/api-keys/:keyIdAPI Keys
9DELETE/api-keys/:keyIdAPI Keys
10GET/plansPlans
11POST/plansPlans
12GET/plans/:idPlans
13PUT/plans/:idPlans
14DELETE/plans/:idPlans
15GET/tenants/:id/subscriptionSubscriptions
16POST/tenants/:id/subscriptionSubscriptions
17DELETE/tenants/:id/subscriptionSubscriptions
18POST/tenants/:id/subscription/portalSubscriptions
19GET/tenants/:id/webhooksWebhooks
20POST/tenants/:id/webhooksWebhooks
21PUT/webhooks/:webhookIdWebhooks
22DELETE/webhooks/:webhookIdWebhooks
23GET/webhooks/:webhookId/deliveriesWebhooks
24POST/webhooks/:webhookId/redeliverWebhooks
25GET/tenants/:id/audit-logsAudit Logs
26POST/tenants/:id/audit-logsAudit Logs
27GET/tenants/:id/audit-logs/statsAudit Logs
28DELETE/tenants/:id/audit-logs/purgeAudit Logs
29GET/tenants/:id/rate-limitsRate Limits
30POST/tenants/:id/rate-limits/resetRate Limits
31GET/tenants/:id/analytics/overviewAnalytics
32GET/tenants/:id/analytics/requestsAnalytics
33GET/tenants/:id/analytics/errorsAnalytics
34GET/tenants/:id/invoicesBilling
35GET/tenants/:id/invoices/:invoiceIdBilling
36POST/tenants/:id/checkoutBilling
37POST/tenants/:id/portalBilling
38GET/healthSystem
39GET/metricsSystem
40POST/stripe/webhookSystem
41POST/stripe/sync-plansSystem

ETags and Conditional Requests

All GET endpoints return ETag headers. You can use If-None-Match to get a 304 Not Modified response when data hasn't changed:

bash
curl -H "Authorization: Bearer tsk_live_..." \
     -H "If-None-Match: \"abc123\"" \
     https://api.tenantscale.com/v1/tenants/tnt_123

Idempotency

POST and PUT requests support idempotency via the Idempotency-Key header:

bash
curl -X POST https://api.tenantscale.com/v1/tenants \
     -H "Authorization: Bearer tsk_live_..." \
     -H "Idempotency-Key: unique-key-123" \
     -d '{"name": "Acme Corp"}'

Idempotency keys expire after 24 hours.


Source: github.com/TenantScale/sdk

Released under the MIT License (SDK) and BSL 1.1 (API).