Admin Reference
Admin endpoints — tenants, partners, roles, permissions, group mappings, sender domains, and tracking settings. These are ScaiSend-native surfaces, not SendGrid-compatible.
Base path: /api/admin/
Auth: JWT-only for most endpoints. API keys can read a narrow subset (domains.read, domains.write for domain endpoints; admin.settings for tracking settings).
Partners#
GET /api/admin/partners#
List partners. A tenant-scoped JWT returns only its own partner.
Response (200):
1 2 3 4 5 | |
GET /api/admin/partners/{partner_id}#
Get a single partner. partner_id can be the local UUID or the ScaiKey ID (prt_xxx).
Response (200): {"data": {...}}.
Tenants#
GET /api/admin/tenants#
List tenants.
Query parameters:
| Parameter | Notes |
|---|---|
partner_id |
Filter by partner (UUID or prt_xxx) |
Non-admin users see only their own tenant. Partner-admin users see every tenant in their partner.
Response (200):
1 2 3 4 5 6 7 8 9 10 11 12 | |
GET /api/admin/tenants/{tenant_id}#
Get a tenant. tenant_id may be the local UUID or the ScaiKey ID.
Response (200): {"data": {...}}.
PATCH /api/admin/tenants/{tenant_id}#
Update a tenant's name or settings.
Request body:
| Field | Notes |
|---|---|
name |
New display name |
settings |
Arbitrary JSON |
GET /api/admin/tenants/{tenant_id}/tracking#
Get tracking settings for a tenant.
Response (200):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
PUT /api/admin/tenants/{tenant_id}/tracking#
Update tracking settings. Partial — unspecified fields keep their value.
Request body: any subset of the response fields above.
Response (200): updated settings.
Permission: admin.settings.
Roles and permissions#
GET /api/admin/permissions#
List all permissions.
Query parameters:
| Parameter | Notes |
|---|---|
category |
Filter by category |
Response (200):
1 2 3 | |
GET /api/admin/permissions/{permission_id}#
Get a single permission.
GET /api/admin/roles#
List roles.
Query parameters:
| Parameter | Notes |
|---|---|
include_permissions |
If true, embed the permissions array |
Response (200):
1 2 3 4 5 6 7 8 9 | |
POST /api/admin/roles#
Create a role.
Request body:
| Field | Type | Required |
|---|---|---|
name |
string | Yes |
description |
string | No |
permission_ids |
array of string | No |
Response (201): role object.
GET /api/admin/roles/{role_id}#
Get a role with permissions.
PATCH /api/admin/roles/{role_id}#
Update name or description.
DELETE /api/admin/roles/{role_id}#
Delete a role. Users holding this role lose these permissions.
PUT /api/admin/roles/{role_id}/permissions#
Replace the role's permission set.
Request body: {"permission_ids": ["perm_mail_send", "perm_stats_read"]}
Response (200): list of permissions now on the role.
POST /api/admin/roles/{role_id}/permissions/{permission_id}#
Add a single permission.
DELETE /api/admin/roles/{role_id}/permissions/{permission_id}#
Remove a single permission.
User roles#
GET /api/admin/users/{user_id}/roles#
List roles held by a user.
Response (200): [RoleResponse].
POST /api/admin/users/{user_id}/roles/{role_id}#
Assign a role to a user.
Response (204): no body.
DELETE /api/admin/users/{user_id}/roles/{role_id}#
Remove a role assignment.
Response (204): no body.
Group mappings#
GET /api/admin/group-mappings#
List ScaiKey group-to-role mappings.
Response (200):
1 2 3 4 5 6 7 8 9 10 11 | |
POST /api/admin/group-mappings#
Create a mapping.
Request body:
| Field | Required |
|---|---|
group_id |
Yes |
role_id |
Yes |
DELETE /api/admin/group-mappings/{mapping_id}#
Delete a mapping.
Sender domains#
GET /api/admin/domains#
List domains.
Query parameters:
| Parameter | Notes |
|---|---|
verified_only |
Return only verified domains |
page |
1-indexed |
page_size |
Items per page |
Response (200):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
POST /api/admin/domains#
Add a domain. ScaiSend generates DKIM keypair and returns DNS records to publish.
Request body:
| Field | Required | Notes |
|---|---|---|
domain |
Yes | Fully qualified domain |
is_shared |
No | If true, usable by any tenant under this partner |
dmarc_policy |
No | none, quarantine, or reject |
dmarc_rua_email |
No | Where DMARC aggregate reports go |
Response (201):
1 2 3 4 5 6 7 8 9 10 11 | |
Permission: domains.write.
GET /api/admin/domains/{domain_id}#
Get a domain with DNS records.
PATCH /api/admin/domains/{domain_id}#
Update domain fields.
Request body: any subset of:
| Field | Notes |
|---|---|
is_active |
Deactivate to prevent further sends |
is_shared |
Toggle shared flag |
dmarc_policy |
Change policy |
dmarc_rua_email |
Change report destination |
DELETE /api/admin/domains/{domain_id}#
Delete a domain. Future sends from this domain fail.
POST /api/admin/domains/{domain_id}/verify#
Run the DNS verification check.
Response (200):
1 2 3 4 5 6 7 8 | |
Permission: domains.write.
POST /api/admin/domains/{domain_id}/rotate-dkim#
Generate a new DKIM keypair under a new selector. Old selector remains active until explicitly removed.
Response (200):
1 2 3 4 5 6 | |
GET /api/admin/domains/{domain_id}/dns-records#
Get the list of DNS records currently required. Idempotent — use if you lost the original POST response.
Response (200):
1 2 3 4 5 | |