Skip to content

Authentication

Overview

SynthesQ supports two authentication mechanisms. Use the one appropriate for your integration type:

MethodUsed byTransport
Bearer token (API token)Third-party integrations, server-to-serverAuthorization: Bearer <token>
Session cookie (Sanctum stateful)SPA / first-party frontendSanctum session cookies

Token management endpoints (/api-tokens/*) are session-authenticated - they are for your frontend to create and manage tokens, and cannot themselves be called with a Bearer token.


Quick Start

Include your API token in the Authorization header of every request:

http
GET /api/v1/operations/products HTTP/1.1
Host: api.synthesq.com
Authorization: Bearer {your-api-token}
Accept: application/json
bash
curl -X GET "https://api.synthesq.com/api/v1/operations/products" \
  -H "Authorization: Bearer {your-api-token}" \
  -H "Accept: application/json"

Token is one-time visible

When you create a token, the plain-text value is returned once only in the plain_text_token field. Store it securely immediately - it cannot be retrieved again.


SPA Session Authentication

First-party SPAs authenticate using Sanctum session cookies. The flow requires a CSRF token before login and supports two-factor authentication.

Login Flow

Step 1 - Obtain a CSRF cookie:

http
GET /sanctum/csrf-cookie HTTP/1.1
Host: api.synthesq.com

This sets the XSRF-TOKEN cookie. Your HTTP client must include this cookie on subsequent requests.

Step 2 - Authenticate:

http
POST /api/v1/auth/login HTTP/1.1
Host: api.synthesq.com
Content-Type: application/json
X-XSRF-TOKEN: {csrf-token-from-cookie}

{
  "email": "jane@example.com",
  "password": "your-password"
}

Responses

200 - Login successful:

json
{
  "success": true,
  "message": "Login successful",
  "data": {
    "user": {
      "id": "01hwxyz123abc456def789ghi0",
      "name": "Jane Smith",
      "email": "jane@example.com",
      "roles": ["sales-manager"]
    }
  }
}

A session cookie is set. All subsequent requests are authenticated automatically via the cookie.

423 - Two-factor authentication required:

json
{
  "success": false,
  "message": "Two-factor authentication required"
}

If the user has two-factor authentication enabled, the login endpoint validates the credentials but does not establish a session. The SPA must prompt the user for their TOTP code and submit it to the two-factor challenge endpoint before access is granted.

Breaking change

SPA clients that previously received a 200 for 2FA-enabled users will now receive 423. Handle this response by presenting a TOTP input to the user.

401 - Invalid credentials:

json
{
  "success": false,
  "message": "Invalid credentials"
}

422 - Validation error:

json
{
  "success": false,
  "message": "The given data was invalid.",
  "errors": {
    "email": ["The email field is required."]
  }
}

Logout

http
POST /api/v1/auth/logout HTTP/1.1
Host: api.synthesq.com
X-XSRF-TOKEN: {csrf-token-from-cookie}

200 - Logged out:

json
{
  "success": true,
  "message": "Logged out successfully"
}

The session is destroyed and the session cookie is invalidated.


Token Types

Three token types are available. Choose based on your use case:

TypeValueDefault ExpiryIP WhitelistingWebhooksBest For
Personal Access Tokenpersonal30 daysNoNoDeveloper testing, short-lived scripts
Application Tokenapplication365 daysNoYesLong-running apps, no IP restriction needed
Integration TokenintegrationNeverYesYesEnterprise integrations requiring IP lock

Expiry behaviour: Default expiry applies when expiration_days is omitted at creation. You can override it with any value from 1 to 3650 days. Integration tokens have no default expiry and remain valid until explicitly revoked.


Token Abilities & Scopes

Format

Every ability string follows the format:

{module}:{action}

Examples: operations:view-products, crm:create-leads, finance:post-journal-entries

Available modules: system, crm, sales, operations, finance, reporting

Wildcard Patterns

Three levels of wildcard are supported, resolved by TokenPermissionMapper:

PatternMeaningExample
*All permissions across all modulesFull admin access
{module}:*All permissions within a moduleoperations:*
{module}:{verb}-*All actions with a given verb prefixoperations:view-*

Example: read-only operations integration

json
["operations:view-*"]

This grants access to operations:view-products, operations:view-inventory, operations:view-suppliers, and all other view-prefixed operations permissions.

Example: full CRM access

json
["crm:*"]

Example: specific abilities

json
["crm:view-leads", "crm:create-leads", "crm:edit-leads"]

Least-privilege principle

Always grant the minimum abilities needed. Avoid * except for trusted system integrations.


Permissions Reference

The tables below list every permission in the system. The ability string is what you include in a token's abilities array. Permissions with High sensitivity require tenant administrator approval before the token is activated.

Sensitivity Levels

LevelSensitivity ScoreRequires Approval
Low10–49No
Medium50–79No
High80–100Yes ✓

System Permissions (system)

AbilityLabelSensitivityApproval
system:manage-systemManage SystemHigh (100)
system:manage-usersManage UsersHigh (100)
system:manage-rolesManage RolesHigh (100)
system:view-audit-logsView Audit LogsLow (30)

CRM Permissions (crm)

Leads

AbilityLabelSensitivityApproval
crm:view-leadsView LeadsLow (25)
crm:create-leadsCreate LeadsLow (30)
crm:edit-leadsEdit LeadsLow (45)
crm:delete-leadsDelete LeadsMedium (65)
crm:assign-leadsAssign LeadsLow (30)
crm:qualify-leadsQualify LeadsLow (30)
crm:convert-leadsConvert LeadsLow (30)
crm:score-leadsScore LeadsLow (30)

Customers

AbilityLabelSensitivityApproval
crm:view-customersView CustomersLow (25)
crm:create-customersCreate CustomersLow (30)
crm:edit-customersEdit CustomersLow (45)
crm:delete-customersDelete CustomersMedium (65)
crm:manage-customer-segmentsManage Customer SegmentsLow (30)
crm:view-customer-clvView Customer CLVLow (30)

Opportunities

AbilityLabelSensitivityApproval
crm:view-opportunitiesView OpportunitiesLow (25)
crm:create-opportunitiesCreate OpportunitiesLow (30)
crm:edit-opportunitiesEdit OpportunitiesLow (45)
crm:delete-opportunitiesDelete OpportunitiesMedium (65)
crm:close-opportunitiesClose OpportunitiesLow (30)
crm:forecast-opportunitiesForecast OpportunitiesLow (30)

Organizations

AbilityLabelSensitivityApproval
crm:view-organizationsView OrganizationsLow (30)
crm:create-organizationsCreate OrganizationsLow (30)
crm:edit-organizationsEdit OrganizationsLow (30)
crm:delete-organizationsDelete OrganizationsLow (30)

Contacts

AbilityLabelSensitivityApproval
crm:view-contactsView ContactsLow (30)
crm:create-contactsCreate ContactsLow (30)
crm:edit-contactsEdit ContactsLow (30)
crm:delete-contactsDelete ContactsLow (30)

Activities

AbilityLabelSensitivityApproval
crm:view-activitiesView ActivitiesLow (30)
crm:create-activitiesCreate ActivitiesLow (30)
crm:edit-activitiesEdit ActivitiesLow (30)
crm:delete-activitiesDelete ActivitiesLow (30)

Campaigns

AbilityLabelSensitivityApproval
crm:view-campaignsView CampaignsLow (30)
crm:create-campaignsCreate CampaignsLow (30)
crm:edit-campaignsEdit CampaignsLow (30)
crm:delete-campaignsDelete CampaignsLow (30)
crm:execute-campaignsExecute CampaignsLow (30)

Sales Permissions (sales)

Orders

AbilityLabelSensitivityApproval
sales:view-ordersView OrdersLow (20)
sales:create-ordersCreate OrdersLow (30)
sales:edit-ordersEdit OrdersLow (30)
sales:delete-ordersDelete OrdersLow (30)
sales:cancel-ordersCancel OrdersLow (30)
sales:ship-ordersShip OrdersLow (30)
sales:complete-ordersComplete OrdersLow (30)
sales:approve-ordersApprove OrdersHigh (85)

Invoices

AbilityLabelSensitivityApproval
sales:view-invoicesView InvoicesLow (20)
sales:create-invoicesCreate InvoicesLow (40)
sales:edit-invoicesEdit InvoicesLow (40)
sales:delete-invoicesDelete InvoicesLow (30)
sales:send-invoicesSend InvoicesMedium (50)
sales:void-invoicesVoid InvoicesMedium (50)

Payments

AbilityLabelSensitivityApproval
sales:view-paymentsView PaymentsLow (30)
sales:process-paymentsProcess PaymentsHigh (80)
sales:refund-paymentsRefund PaymentsHigh (80)
sales:view-payment-detailsView Payment DetailsHigh (80)

Pricing

AbilityLabelSensitivityApproval
sales:apply-discountsApply DiscountsLow (40)
sales:override-pricingOverride PricingHigh (85)
sales:manage-commissionManage CommissionMedium (50)

Operations Permissions (operations)

Products

AbilityLabelSensitivityApproval
operations:view-productsView ProductsLow (20)
operations:create-productsCreate ProductsLow (30)
operations:edit-productsEdit ProductsLow (35)
operations:delete-productsDelete ProductsLow (30)
operations:discontinue-productsDiscontinue ProductsLow (30)
operations:manage-product-categoriesManage Product CategoriesLow (30)
operations:manage-product-attributesManage Product AttributesLow (30)

Inventory

AbilityLabelSensitivityApproval
operations:view-inventoryView InventoryLow (15)
operations:manage-inventoryManage InventoryLow (35)
operations:adjust-stockAdjust StockMedium (60)
operations:transfer-stockTransfer StockMedium (60)
operations:reserve-stockReserve StockLow (30)
operations:release-stockRelease StockLow (30)

Suppliers

AbilityLabelSensitivityApproval
operations:view-suppliersView SuppliersLow (15)
operations:create-suppliersCreate SuppliersLow (30)
operations:edit-suppliersEdit SuppliersLow (35)
operations:delete-suppliersDelete SuppliersLow (30)
operations:rate-suppliersRate SuppliersMedium (60)
operations:manage-supplier-contractsManage Supplier ContractsLow (30)

Purchase Orders

AbilityLabelSensitivityApproval
operations:view-purchase-ordersView Purchase OrdersLow (30)
operations:create-purchase-ordersCreate Purchase OrdersLow (30)
operations:edit-purchase-ordersEdit Purchase OrdersLow (30)
operations:delete-purchase-ordersDelete Purchase OrdersLow (30)
operations:approve-purchase-ordersApprove Purchase OrdersHigh (85)
operations:send-purchase-ordersSend Purchase OrdersLow (30)
operations:receive-goodsReceive GoodsLow (30)

Coupons

AbilityLabelSensitivityApproval
operations:manage-couponsManage CouponsLow (30)
operations:apply-couponsApply CouponsLow (30)

Finance Permissions (finance)

Accounts

AbilityLabelSensitivityApproval
finance:view-accountsView AccountsLow (15)
finance:create-accountsCreate AccountsMedium (55)
finance:edit-accountsEdit AccountsMedium (55)
finance:delete-accountsDelete AccountsHigh (90)
finance:activate-accountsActivate AccountsLow (30)
finance:deactivate-accountsDeactivate AccountsLow (30)

Journal Entries

AbilityLabelSensitivityApproval
finance:view-journal-entriesView Journal EntriesMedium (55)
finance:create-journal-entriesCreate Journal EntriesMedium (75)
finance:edit-journal-entriesEdit Journal EntriesMedium (75)
finance:delete-journal-entriesDelete Journal EntriesLow (30)
finance:post-journal-entriesPost Journal EntriesHigh (95)
finance:reverse-journal-entriesReverse Journal EntriesHigh (95)

Financial Reports

AbilityLabelSensitivityApproval
finance:view-financial-reportsView Financial ReportsMedium (70)
finance:generate-financial-reportsGenerate Financial ReportsLow (30)
finance:export-financial-dataExport Financial DataMedium (70)

Budgets, Expenses & Configuration

AbilityLabelSensitivityApproval
finance:manage-budgetsManage BudgetsMedium (75)
finance:approve-expensesApprove ExpensesHigh (90)
finance:reconcile-accountsReconcile AccountsHigh (90)
finance:view-sensitive-financial-dataView Sensitive Financial DataHigh (95)
finance:manage-tax-configurationManage Tax ConfigurationHigh (95)

Reporting Permissions (reporting)

AbilityLabelSensitivityApproval
reporting:view-reportsView ReportsLow (10)
reporting:create-reportsCreate ReportsLow (30)
reporting:share-reportsShare ReportsLow (30)
reporting:export-dataExport DataLow (30)
reporting:view-analyticsView AnalyticsLow (10)
reporting:view-dashboardView DashboardLow (10)

Roles Reference

Roles define what a user can do within the system. They are assigned by tenant administrators and determine which API abilities can be granted to tokens the user creates.

Hierarchy

RoleLabelLevelModule ScopeApproval Limit
super-adminSuper Administrator100All modules$1,000,000
system-adminSystem Administrator95-$5,000
crm-adminCRM Administrator90crm$5,000
sales-adminSales Administrator90sales$100,000
operations-adminOperations Administrator90operations$500,000
finance-adminFinance Administrator90finance$500,000
crm-managerCRM Manager80crm$5,000
sales-managerSales Manager80sales$100,000
operations-managerOperations Manager80operations$250,000
finance-managerFinance Manager80finance$250,000
reporting-analystReporting Analyst75-$5,000
sales-representativeSales Representative72sales$5,000
account-managerAccount Manager72sales$5,000
customer-supportCustomer Support Specialist72crm$5,000
senior-accountantSenior Accountant70finance$50,000
sales-repSales Representative70sales$25,000
accountantAccountant70finance$25,000
procurement-specialistProcurement Specialist70operations$50,000
customer-serviceCustomer Service Representative60crm$5,000
inventory-clerkInventory Clerk60operations$10,000
junior-sales-repJunior Sales Representative50sales$5,000
junior-accountantJunior Accountant50finance$5,000
data-entry-clerkData Entry Clerk40-$5,000

Approval limit is the maximum financial transaction value the role can approve without escalation.

Module scope determines which modules the role can manage. super-admin manages all modules.

Default Permissions by Role

RoleDefault Permission Set
super-adminAll permissions
crm-adminAll crm:* + all reporting:*
sales-adminAll sales:* + all crm:* + all reporting:*
operations-adminAll operations:* + all reporting:*
finance-adminAll finance:* + all reporting:*

Rate Limiting

All API token requests are subject to rate limiting based on the token's tier.

Tiers

TierValueRequests per MinuteBurst Allowed
Basicbasic60No
Standardstandard300Yes
Premiumpremium600Yes
Unlimitedunlimited999,999Yes

Set the tier when creating a token via the rate_limit_tier field. If omitted, the system assigns a default tier.

Response Headers

Every API response includes rate limit headers:

HeaderPresent whenDescription
X-RateLimit-LimitAlwaysMaximum requests per minute for this token
X-RateLimit-RemainingAlwaysRemaining requests in the current window
Retry-AfterOn 429 onlySeconds until the window resets
X-RateLimit-ResetOn 429 onlyUnix timestamp when the window resets

429 Too Many Requests

json
{
  "message": "Too many requests. Please try again later."
}

Headers on 429:

http
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
Retry-After: 45
X-RateLimit-Reset: 1737028245

Token Management

Token management endpoints are session-authenticated (SPA / first-party frontend only). They are not accessible via Bearer token. Authenticate your frontend via Sanctum stateful sessions before calling these endpoints.

Endpoints

MethodPathDescription
GET/api-tokensList all tokens for the authenticated user
POST/api-tokensCreate a new API token
GET/api-tokens/{id}Get a specific token's details
DELETE/api-tokens/{id}Delete a token permanently
POST/api-tokens/{id}/revokeRevoke a token (soft-disable, keeps audit trail)
POST/api-tokens/{id}/rotateRotate token - invalidates old, issues new
GET/api-tokens/{id}/usageGet token usage statistics

Create Token - POST /api-tokens

Request body:

json
{
  "name": "My Integration",
  "token_type": "integration",
  "abilities": ["operations:view-products", "operations:view-inventory"],
  "description": "Read-only access for ERP sync",
  "rate_limit_tier": "standard",
  "expiration_days": null,
  "allowed_ips": ["203.0.113.10", "203.0.113.11"],
  "webhook_url": "https://my-app.example.com/webhooks/crm"
}
FieldTypeRequiredDescription
namestringYesHuman-readable token name (max 255 chars)
token_typestringYespersonal, application, or integration
abilitiesarrayYesAbility strings the token can use
descriptionstringNoOptional description (max 500 chars)
rate_limit_tierstringNobasic, standard, premium, or unlimited
expiration_daysinteger|nullNoDays until expiry (1–3650). null = no expiry
allowed_ipsarray|nullNoIP whitelist - integration tokens only
webhook_urlstring|nullNoWebhook URL - application and integration tokens only

Response 201 Created:

json
{
  "success": true,
  "message": "API token created successfully",
  "data": {
    "id": "01hwxyz123abc456def789ghn0",
    "name": "My Integration",
    "description": "Read-only access for ERP sync",
    "token_type": "integration",
    "token_type_label": "Integration Token",
    "abilities": ["operations:view-products", "operations:view-inventory"],
    "rate_limit": {
      "tier": "standard",
      "tier_label": "Standard (300/min)",
      "requests_per_minute": 300
    },
    "usage": {
      "request_count": 0,
      "first_used_at": null,
      "last_used_at": null
    },
    "security": {
      "allowed_ips": ["203.0.113.10", "203.0.113.11"],
      "has_ip_restriction": true,
      "webhook_url": "https://my-app.example.com/webhooks/crm"
    },
    "status": {
      "is_active": true,
      "is_expired": false,
      "is_revoked": false,
      "revoked_at": null,
      "revoked_by": null,
      "revocation_reason": null
    },
    "rotation": {
      "rotated_at": null,
      "rotated_from_token_id": null
    },
    "expires_at": null,
    "created_at": "2026-01-15T10:30:00+00:00",
    "updated_at": "2026-01-15T10:30:00+00:00"
  },
  "plain_text_token": "1|abcdef1234567890..."
}

One-time token visibility

plain_text_token is only returned once at creation time. It cannot be retrieved again. Copy and store it securely before closing the response.


Advanced Features

IP Whitelisting

integration tokens support an allowed_ips array. When set, every request using that token is checked against the list by the CheckTokenIpWhitelist middleware.

  • Requests from IPs not in the list are rejected immediately with 403 Forbidden:
    json
    { "message": "Access denied. Your IP address is not whitelisted for this token." }
  • Requests from whitelisted IPs proceed normally.
  • personal and application tokens do not support IP whitelisting.

Example: restricting to your office and CI/CD IP ranges

json
{
  "token_type": "integration",
  "allowed_ips": ["203.0.113.10", "203.0.113.20", "198.51.100.0"]
}

Webhooks

application and integration tokens accept an optional webhook_url. The system dispatches webhook events asynchronously via SendTokenWebhookJob when token lifecycle events occur:

EventTrigger
token.createdA new token is created
token.rotatedA token is rotated (old invalidated, new issued)
token.revokedA token is revoked

Webhook payload:

json
{
  "event": "token.created",
  "timestamp": "2026-01-15T10:30:00+00:00",
  "data": { }
}

Webhook headers:

HeaderValue
Content-Typeapplication/json
X-Webhook-EventThe event name (e.g. token.created)
X-Webhook-SignatureHMAC-SHA256 signature of the payload body

Verifying the signature:

The signature is computed as HMAC-SHA256(json_encode(payload), webhook_secret). Verify it on your receiver to ensure authenticity. The webhook secret is configured by your tenant administrator.

Webhook delivery is attempted up to 3 times with a 60-second backoff between retries. Delivery times out after 10 seconds per attempt.

Token Rotation

POST /api-tokens/{id}/rotate invalidates the current token and issues a replacement with the same abilities and configuration. The response includes a new plain_text_token - store it immediately.

The original token's rotation.rotated_at and new token's rotation.rotated_from_token_id fields track the rotation chain for audit purposes.

Use rotation to refresh long-lived tokens periodically without disrupting integrations.


Sensitive Permissions & Approval

The following permissions have a sensitivity level ≥ 80 and require tenant administrator approval before a token requesting them is activated:

System

  • system:manage-system, system:manage-users, system:manage-roles

Sales

  • sales:approve-orders, sales:override-pricing
  • sales:process-payments, sales:refund-payments, sales:view-payment-details

Operations

  • operations:approve-purchase-orders

Finance

  • finance:delete-accounts, finance:approve-expenses, finance:reconcile-accounts
  • finance:post-journal-entries, finance:reverse-journal-entries
  • finance:view-sensitive-financial-data, finance:manage-tax-configuration

Contact your tenant administrator if a token you created with these abilities is not yet active.


Security Best Practices

Token Storage

  • Never store tokens in source code or version control
  • Use encrypted secrets management (HashiCorp Vault, AWS Secrets Manager, environment variables)
  • Use separate tokens for each integration - never share tokens between systems
  • Use integration token type with IP whitelisting for production enterprise integrations

Token Lifecycle

  • Grant the minimum abilities needed for each integration (least-privilege)
  • Set explicit expiration_days for tokens used in scripts or temporary workflows
  • Rotate tokens periodically with POST /api-tokens/{id}/rotate
  • Revoke tokens immediately when an integration is retired or a secret is compromised

Token Transmission

  • Always use HTTPS - never send tokens over unencrypted connections
  • Pass tokens via the Authorization: Bearer header only - never in URL query parameters
  • Exclude tokens from application logs and error reporting

Error Reference

401 Unauthorized

Token is missing, malformed, expired, or the Sanctum session has ended.

json
{ "message": "Unauthenticated" }

Resolution: Check that the Authorization: Bearer {token} header is present and the token has not expired. If expired, create a new token via the SPA.

403 Forbidden

Token is valid but lacks the required ability for the endpoint, or the client IP is not whitelisted.

Insufficient abilities:

json
{
  "message": "Insufficient token abilities",
  "required": ["operations:create-products"],
  "token_abilities": ["operations:view-products"]
}

IP not whitelisted (integration tokens):

json
{ "message": "Access denied. Your IP address is not whitelisted for this token." }

Resolution: Verify the token's abilities include what the endpoint requires, or contact your administrator to update the token. For IP errors, ensure the request originates from a whitelisted address.

423 Locked (Two-Factor Required)

The user's credentials are valid but two-factor authentication must be completed before a session is granted. This applies to both the SPA login endpoint and the Gateway auth proxy.

json
{ "success": false, "message": "Two-factor authentication required" }

Resolution: Prompt the user for their TOTP code and submit it to the two-factor challenge endpoint.

429 Too Many Requests

Rate limit exceeded for this token.

json
{ "message": "Too many requests. Please try again later." }

Inspect the Retry-After header for the number of seconds to wait before retrying.


Documentation for SynthesQ CRM/ERP Platform