Sintj API (1.30.0)

Download OpenAPI specification:

Sintj Rails 8.1 API — spec-first, contract-validated.

Auth

Stytch B2B OAuth login (start/callback/session exchange) and session identity (auth_engine pack)

Return the authenticated account's identity

Returns the account id and email for the caller identified by the _sintj_session cookie.

Authorizations:
SessionCookie

Responses

Response samples

Content type
application/json
{
  • "account": {
    }
}

Start a Stytch B2B OAuth login for a tenant

Redirects the browser to Stytch's hosted OAuth start URL for the given tenant (identified by slug) and provider. Not JSON — a 302 browser redirect.

path Parameters
provider
required
string
Enum: "google" "microsoft"
Example: google
query Parameters
org
required
string
Example: org=acme

Tenant slug

return_to
string
Example: return_to=/tenant/dashboard

Path within the tenant app to land on after login completes

Responses

Response samples

Content type
application/json
{
  • "error_code": "auth.provider_not_allowed",
  • "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Stytch OAuth callback — fixed host first, then the tenant's own host

Reached twice in sequence for a single login: first at the fixed Stytch-registered redirect URI (shared across every tenant and region, since OAuth providers don't allow per-tenant redirect URIs), where the Cloudflare Worker rewrites the request into a 302 to this same path on the tenant's own host (subdomain or custom domain) — that hop is Worker-side and not a Rails request. Carries only token — Stytch validates redirect URLs by exact match including query string, so no other params can ride on it. The tenant is resolved from the organization_id in Stytch's authenticated response, and return_to (captured at /{provider}/start) travels in a short-lived cookie, not a query param. On the tenant's own host, Rails verifies the OAuth token via Stytch, finds-or-creates the local account, sets the real session cookie, and redirects to return_to. Not JSON — a 302 browser redirect.

query Parameters
token
required
string
Example: token=rTPQqcSuKpjbUhqWahYNVLbZzUE6hHMPRB6qxvExeGYy

Stytch OAuth token appended by Stytch after the provider completes

Responses

Response samples

Content type
application/json
{
  • "error_code": "auth.unauthorized",
  • "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Log in with email and password

Verifies the password against Stytch (not a locally-stored hash) for the given tenant's Organization. On success, sets the _sintj_session cookie and returns 204.

Request Body schema: application/json
required
required
object (PasswordLoginInput)

Responses

Request samples

Content type
application/json
{
  • "session": {
    }
}

Response samples

Content type
application/json
{
  • "error_code": "auth.unauthorized",
  • "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Log out

Clears the _sintj_session cookie. Idempotent — returns 204 whether or not a session cookie was present.

Responses

Health

Service health and liveness

Health check

Returns 200 when the service is running. No authentication required.

Responses

Response samples

Content type
application/json
{
  • "status": "ok"
}

Tenants

Tenant provisioning (internal admin API)

Get tenant detail

Returns a tenant's full record including per-step onboarding status. Requires an internal service key — not exposed to end users.

Authorizations:
ServiceJWT
path Parameters
id
required
string <uuid>
Example: 7c9e6679-7425-40de-944b-e07fc1f90ae7

Responses

Response samples

Content type
application/json
{
  • "tenant": {
    }
}

Soft-delete a tenant

Soft-deletes a tenant by setting deleted_at. Only disabled tenants may be deleted; attempting to delete an active tenant returns 422. Requires an internal service key — not exposed to end users.

Authorizations:
ServiceJWT
path Parameters
id
required
string <uuid>
Example: 7c9e6679-7425-40de-944b-e07fc1f90ae7

Responses

Response samples

Content type
application/json
{
  • "error_code": "auth.unauthorized",
  • "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

List all tenants

Returns all provisioned tenants with their aggregate onboarding status. Requires an internal service key — not exposed to end users.

Authorizations:
ServiceJWT

Responses

Response samples

Content type
application/json
{
  • "tenants": [
    ]
}

Provision a new tenant

Creates a tenant record and seeds pending onboarding status rows. Requires an internal service key — not exposed to end users.

Authorizations:
ServiceJWT
Request Body schema: application/json
required
required
object (TenantInput)

Responses

Request samples

Content type
application/json
{
  • "tenant": {
    }
}

Response samples

Content type
application/json
{
  • "success": true,
  • "id": "550e8400-e29b-41d4-a716-446655440000"
}

Enable a tenant

Sets a tenant's status to active. Idempotent — enabling an already-active tenant is a no-op and still returns 200. Requires an internal service key.

Authorizations:
ServiceJWT
path Parameters
id
required
string <uuid>
Example: 7c9e6679-7425-40de-944b-e07fc1f90ae7

Responses

Response samples

Content type
application/json
{
  • "success": true,
  • "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
}

Disable a tenant

Sets a tenant's status to disabled. Idempotent — disabling an already-disabled tenant is a no-op and still returns 200. Requires an internal service key.

Authorizations:
ServiceJWT
path Parameters
id
required
string <uuid>
Example: 7c9e6679-7425-40de-944b-e07fc1f90ae7

Responses

Response samples

Content type
application/json
{
  • "success": true,
  • "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
}

Local-dev mirror of a tenant's Cloudflare KV routing record

Returns the same {tenant_id, slug, host, region, allowed_auth_methods} record normally pushed to Cloudflare KV (Platform::SyncTenantKvService), so a local frontend/Worker (e.g. wrangler dev without --remote) can resolve tenant routing without real remote KV credentials. Public and unauthenticated, but development-environment only — returns 404 in every other environment. Never available in production.

path Parameters
slug
required
string
Example: acme

Responses

Response samples

Content type
application/json
{
  • "tenant_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  • "slug": "acme",
  • "host": "acme.sintj.com",
  • "region": "us",
  • "allowed_auth_methods": [
    ]
}

Workspaces

Workspace management within a tenant (internal admin API)

Create a workspace for a tenant

Creates a new workspace under an existing tenant. Requires a valid X-Schema-Name header identifying the tenant schema.

header Parameters
X-Schema-Name
required
string
Example: acme_1234

Stable Apartment schema name of the tenant

Request Body schema: application/json
required
required
object (WorkspaceInput)

Responses

Request samples

Content type
application/json
{
  • "workspace": {
    }
}

Response samples

Content type
application/json
{
  • "success": true,
  • "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}

Assign a user to a workspace

Assigns an existing user to a workspace with a given role. Duplicate assignments are rejected with a 422 validation error. Requires a valid X-Schema-Name header.

header Parameters
X-Schema-Name
required
string
Example: acme_1234

Stable Apartment schema name of the tenant

Request Body schema: application/json
required
required
object (WorkspaceUserInput)

Responses

Request samples

Content type
application/json
{
  • "workspace_user": {
    }
}

Response samples

Content type
application/json
{
  • "success": true
}

WorkspaceUsers

Assign users to workspaces within a tenant (internal admin API)

Users

Customer user management within a tenant schema (internal admin API)

Invite a user to the tenant (stub — SIN-1329)

Initiates the invitation flow for a new tenant user: creates a Stytch member, seeds a Tenant::User record with status "invited", and sends an invitation email. Not yet implemented — returns 501 until SIN-1329 is complete. Full contract (200 success + 422 validation error) added when SIN-1329 ships. Requires a valid X-Schema-Name header identifying the tenant schema.

header Parameters
X-Schema-Name
required
string
Example: acme_1234

Stable Apartment schema name of the tenant

Request Body schema: application/json
required
required
object (UserInput)

Responses

Request samples

Content type
application/json
{
  • "user": {
    }
}

Response samples

Content type
application/json
{
  • "error_code": "api.not_implemented",
  • "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Enable a tenant user

Sets a tenant user's status to "active". Idempotent — enabling an already-active user succeeds. Requires a valid X-Schema-Name header identifying the tenant schema.

path Parameters
id
required
string <uuid>
Example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
header Parameters
X-Schema-Name
required
string
Example: acme_1234

Stable Apartment schema name of the tenant

Responses

Response samples

Content type
application/json
{
  • "success": true,
  • "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Disable a tenant user

Sets a tenant user's status to "disabled", preventing login. Idempotent. Requires a valid X-Schema-Name header identifying the tenant schema.

path Parameters
id
required
string <uuid>
Example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
header Parameters
X-Schema-Name
required
string
Example: acme_1234

Stable Apartment schema name of the tenant

Responses

Response samples

Content type
application/json
{
  • "success": true,
  • "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Invitations

Owner invitation flow — invite (platform_engine) and accept (tenant_engine)

Invite the tenant owner

Creates a Platform::User record (status: invited) and a mirrored Tenant::User in the tenant's Apartment schema, then sends an invitation email with an accept link. Guards: schema_provisioning step must be completed; no Platform::User may exist yet for this tenant. Requires an internal service key.

Authorizations:
ServiceJWT
path Parameters
id
required
string <uuid>
Example: 7c9e6679-7425-40de-944b-e07fc1f90ae7
Request Body schema: application/json
required
required
object (InvitationInput)

Responses

Request samples

Content type
application/json
{
  • "invitation": {
    }
}

Response samples

Content type
application/json
{
  • "success": true,
  • "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
}

Accept an owner invitation

Validates the invitation token, sets the owner's password and name, flips both the Platform::User and Tenant::User to status active, and records invitation_accepted_at. No authentication header required — the token in the URL is the auth factor.

path Parameters
token
required
string
Example: a3f8b2c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1
Request Body schema: application/json
required
required
object (AcceptInvitationInput)

Responses

Request samples

Content type
application/json
{
  • "invitation": {
    }
}

Response samples

Content type
application/json
{
  • "success": true
}

OrgSettings

Tenant-level authentication policy settings (tenant_engine)

Update tenant org settings

Partial update of the tenant's authentication policy settings. Only keys present in the request body are written; omitted keys are left unchanged. Unknown keys are silently ignored. The legacy mfa_required key is never written by this endpoint. Requires a valid X-Schema-Name header identifying the tenant schema.

header Parameters
X-Schema-Name
required
string
Example: acme_1234

Stable Apartment schema name of the tenant

Request Body schema: application/json
required
required
object (OrgSettingsInput)

Partial update — only keys present in the request body are written. Unknown keys are silently ignored. Allowed values are strings only (the OrgSettings table is a key-value store). The legacy mfa_required key must not be sent; use mfa_mode instead.

Responses

Request samples

Content type
application/json
{
  • "org_settings": {
    }
}

Response samples

Content type
application/json
{
  • "success": true
}

Internal

Service-to-service endpoints, authenticated via X-Service-JWT (never exposed to end users)

Provision an Apartment schema in this zone

Internal endpoint called by the central provisioning service to create an Apartment PostgreSQL schema for a tenant in this zone's database and seed OrgSettings defaults. Idempotent — returns 200 if the schema already exists. Authenticated via X-Service-JWT — never exposed to end users.

Authorizations:
ServiceJWT
path Parameters
tenant_id
required
string <uuid>
Example: 7c9e6679-7425-40de-944b-e07fc1f90ae7
Request Body schema: application/json
required
required
object (ProvisionSchemaInput)

Responses

Request samples

Content type
application/json
{
  • "schema": {
    }
}

Response samples

Content type
application/json
{
  • "success": true
}