Hydrix Docs

API

Site Admin and Data API surfaces.

Use this page to integrate every site-facing /admin/* and /data/* route exposed on a Hydrix site domain. All paths below are the public site-domain paths, not internal or stage-prefixed service routes.

Admin API

  • /admin/public bootstrap, contact, verification, and onboarding routes
  • /admin/api users, mailboxes, aliases, messages, profiles, branding, and invites
  • /admin/data resources, operations, jobs, groups, env vars, compute, and IaC

Data API

  • GET /data/auth/config runtime auth discovery
  • GET /data/public/auth/config public alias for auth discovery
  • GET /data/auth/methods current visitor sign-in methods
  • POST /data/auth/providers/google/link/start explicit Google-link flow start
  • POST /data/auth/password/add add password sign-in to a Google-only account
  • POST /data/public/{operation} public runtime operations
  • POST /data/{operation} authenticated runtime operations

Common Rules

  • /admin/api/* and /admin/data/* use the site admin user pool
  • /data/{operation} uses the site data-system access token
  • Responses are JSON with client-safe error messages and no infrastructure details

Auth Boundary

Route Family Token Who Uses It
/admin/public/* No token Anonymous bootstrap and public workflow routes.
/admin/api/profile Admin user pool JWT Any signed-in site user for their own profile.
/admin/api/mailboxes/* and /admin/api/messages/* Admin user pool JWT Admins can access any mailbox. Regular users are limited to owned mailboxes.
/admin/api/* other routes Admin user pool JWT Admin or super-admin site-management actions.
/admin/api/auth-email-branding
/admin/api/super-admin-invites/resend
Admin user pool JWT Super-admin only.
/admin/data/* Admin user pool JWT Admin or super-admin data-control actions.
/data/auth/config
/data/public/auth/config
No token Site application auth discovery.
/data/auth/methods Data-system access token Current visitor sign-in method discovery.
/data/auth/providers/google/link/start
/data/auth/password/add
Data-system access token Visitor sign-in method management for explicit Google link and add-password flows.
/data/public/{operation} No token Public site runtime operations.
/data/{operation} Data-system access token Authenticated visitor or site-application runtime operations.

Admin Conventions

  • Responses return the endpoint payload directly, not a Lambda proxy wrapper.
  • Timestamps use ISO-8601 UTC strings.
  • Pagination uses limit and nextToken.
  • GET /admin/api/users returns at most 50 users per call; continue with nextToken to fetch the rest.

Data Conventions

  • Data routes accept JSON and forward the request as a payload.
  • Responses use { ok, data?, error? }.
  • GET /data/auth/config and GET /data/auth/methods are the supported GET routes.

Provisioning Behavior

  • /admin/data/* routes can return retryable provisioning states while runtime initializes.
  • Internal runtime, control-shard, and execute-api aliases are intentionally excluded from this contract.
  • Errors are sanitized before they reach site clients.

/admin/public Routes

These routes are intentionally anonymous. They bootstrap the admin app, accept public contact-form submissions, verify forwarding targets, and complete onboarding flows from emailed invite links.

Method Path Purpose Access
GET
/admin/public/config Payload and response
Loads admin SPA bootstrap config: site identity, base path, and Cognito Hosted UI or custom-login settings. No token.
POST
/admin/public/contact Payload and response
Sends the site contact form to configured contact recipients with the submitter as Reply-To. No token. WAF rate-limited.
GET
/admin/public/forwarding/verify Payload and response
Confirms an external forwarding target from the verification link delivered to that external inbox. No token. Query-string token required.
GET
/admin/public/onboarding/super-admin Payload and response
Renders the Hydrix-hosted password setup page for a super-admin invite token. No token. Query-string token required.
POST
/admin/public/onboarding/super-admin Payload and response
Sets the password and redeems a super-admin onboarding token. No token. Token and password are submitted in the form body.
GET
/admin/public/onboarding/user Payload and response
Renders the Hydrix-hosted password setup page for a regular user invite token. No token. Query-string token required.
POST
/admin/public/onboarding/user Payload and response
Sets the password and redeems a regular user onboarding token. No token. Token and password are submitted in the form body.

Route examples

GET /admin/public/config Bootstrap config
Request

No request body.

Response example
{
  "siteId": "site_123",
  "siteDomain": "example.com",
  "region": "us-east-1",
  "api": {
    "basePath": "/admin/api"
  },
  "auth": {
    "clientId": "1exampleclientid",
    "domain": "https://example.auth.us-east-1.amazoncognito.com",
    "scope": ["openid", "email", "profile"],
    "redirectUri": "https://example.com/admin/callback",
    "logoutUri": "https://example.com/admin/logout"
  }
}
POST /admin/public/contact Contact form submit
Payload example
{
  "name": "Ada Lovelace",
  "email": "ada@example.org",
  "phone": "555-0100",
  "subject": "New project inquiry",
  "message": "We would like to talk about a new site build.",
  "metadata": {
    "company": "Example Co",
    "budget": "10k-25k"
  }
}
Response example
{
  "messageId": "ses-message-id"
}
GET /admin/public/forwarding/verify Forwarding verification
Query example
{
  "mailbox": "support@example.com",
  "target": "person@gmail.com",
  "token": "forwarding-token"
}
Response example
{
  "mailbox": "support@example.com",
  "target": "person@gmail.com",
  "status": "VERIFIED"
}
GET /admin/public/onboarding/super-admin Super-admin onboarding page
Query example
{
  "token": "super-admin-onboarding-token"
}
Response

Returns a Hydrix-hosted HTML password setup page, not JSON.

POST /admin/public/onboarding/super-admin Redeem super-admin invite
Form example
{
  "token": "super-admin-onboarding-token",
  "password": "StrongPassword!123",
  "confirmPassword": "StrongPassword!123"
}
Response

Returns a Hydrix-hosted HTML success page or validation-error page, not JSON.

GET /admin/public/onboarding/user User onboarding page
Query example
{
  "token": "user-onboarding-token"
}
Response

Returns a Hydrix-hosted HTML password setup page, not JSON.

POST /admin/public/onboarding/user Redeem user invite
Form example
{
  "token": "user-onboarding-token",
  "password": "StrongPassword!123",
  "confirmPassword": "StrongPassword!123"
}
Response

Returns a Hydrix-hosted HTML success page or validation-error page, not JSON.

Data Auth Management

Hydrix data auth now supports explicit visitor sign-in method management without exposing admin-only APIs. Google link completion happens inside Cognito's pre-sign-up flow for a dedicated link client, while the frontend keeps PKCE state and exchanges the callback code with Cognito directly.

Method Path Purpose
GET /data/auth/methods Returns whether the current account already has password and Google sign-in enabled.
POST /data/auth/providers/google/link/start Returns the Cognito Hosted UI Google authorize URL for explicit account linking.
POST /data/auth/password/add Adds local password sign-in to the currently authenticated Google-only account.

/admin/api Routes

These routes power the admin experience for users, mailboxes, aliases, messages, and site settings. They all use the site admin user pool, and mailbox-sensitive routes enforce owner rules for regular users.

Users and Profiles

Method Path Purpose Access
POST
/admin/api/users Payload and response
Creates a site user, assigns the requested role, and sends the Hydrix onboarding email. Admin or super-admin.
GET
/admin/api/users Payload and response
Lists site users with role and profile summary data. Admin or super-admin.
GET
/admin/api/users/{userId}/profile Payload and response
Reads a specific user profile, including primary email, optional external email, and settings. Admin or super-admin.
PUT
/admin/api/users/{userId}/profile Payload and response
Updates a specific user profile, including active email behavior and per-user settings. Admin or super-admin.
DELETE
/admin/api/users/{userId} Payload and response
Deletes a user and applies mailbox-ownership safety rules before removal. Admin or super-admin.
GET
/admin/api/profile Payload and response
Loads the signed-in user’s own profile and client settings. Any signed-in site user.
PUT
/admin/api/profile Payload and response
Updates the signed-in user’s own profile and client settings. Any signed-in site user.

Route examples

POST /admin/api/usersCreate a site user
Payload example
{
  "email": "alice@example.com",
  "role": "admin",
  "externalEmail": "alice.personal@example.org"
}
Response example
{
  "userId": "user_123",
  "email": "alice@example.com",
  "role": "admin",
  "externalEmail": "alice.personal@example.org",
  "inviteSent": true,
  "inviteRecipient": "alice@example.com"
}
GET /admin/api/usersList users
Query example
{
  "limit": 50,
  "nextToken": "opaque-token"
}
Response example
{
  "items": [
    {
      "userId": "user_123",
      "email": "alice@example.com",
      "role": "admin",
      "externalEmail": "alice.personal@example.org"
    }
  ],
  "nextToken": "opaque-token"
}
Pagination notes
Repeat the request with nextToken until it is null or omitted.
The route returns at most 50 users per response.
GET /admin/api/users/{userId}/profileRead a user profile
Path example
{
  "userId": "user_123"
}
Response example
{
  "userSub": "sub_123",
  "primaryEmail": "alice@example.com",
  "activeEmail": "alice@example.com",
  "externalEmail": "alice.personal@example.org",
  "settings": {
    "signature": "Sent from Hydrix"
  },
  "createdAt": "2026-03-20T15:00:00.000Z",
  "updatedAt": "2026-03-20T15:00:00.000Z"
}
PUT /admin/api/users/{userId}/profileUpdate a user profile
Payload example
{
  "primaryEmail": "alice@example.com",
  "externalEmail": "alice.personal@example.org",
  "settings": {
    "signature": "Sent from Hydrix"
  }
}
Response example
{
  "userSub": "sub_123",
  "primaryEmail": "alice@example.com",
  "activeEmail": "alice@example.com",
  "externalEmail": "alice.personal@example.org",
  "settings": {
    "signature": "Sent from Hydrix"
  },
  "updatedAt": "2026-03-20T15:30:00.000Z"
}
DELETE /admin/api/users/{userId}Remove a user
Path example
{
  "userId": "user_123"
}
Response

Returns 204 No Content on success. It can also return 409 MailboxOwnershipConflict if mailbox ownership cannot be reassigned safely.

GET /admin/api/profileRead your own profile
Request

No request body.

Response example
{
  "userSub": "sub_123",
  "primaryEmail": "alice@example.com",
  "activeEmail": "alice@example.com",
  "externalEmail": "alice.personal@example.org",
  "settings": {
    "theme": "system"
  }
}
PUT /admin/api/profileUpdate your own profile
Payload example
{
  "primaryEmail": "alice@example.com",
  "activeEmail": "alice@example.com",
  "externalEmail": "alice.personal@example.org",
  "settings": {
    "theme": "system"
  }
}
Response example
{
  "userSub": "sub_123",
  "primaryEmail": "alice@example.com",
  "activeEmail": "alice@example.com",
  "externalEmail": "alice.personal@example.org",
  "settings": {
    "theme": "system"
  },
  "updatedAt": "2026-03-20T15:30:00.000Z"
}

Mailboxes, Forwarding, and Aliases

Method Path Purpose Access
POST
/admin/api/mailboxes Payload and response
Creates a mailbox and assigns the initial owners. Admin or super-admin.
GET
/admin/api/mailboxes Payload and response
Lists mailboxes visible to the caller. Admins see all. Users see owned mailboxes.
PATCH
/admin/api/mailboxes/{address} Payload and response
Replaces the owner list for one mailbox. Admin or super-admin.
DELETE
/admin/api/mailboxes/{address} Payload and response
Disables a mailbox without deleting historical mail. Admin or super-admin.
POST
/admin/api/mailboxes/{address}/purge Payload and response
Permanently removes a mailbox and cascades mailbox-specific cleanup. Super-admin only.
POST
/admin/api/mailboxes/{address}/restore Payload and response
Re-enables a disabled mailbox and restores owner assignments. Admin or super-admin.
GET
/admin/api/mailboxes/{address}/settings Payload and response
Reads trash auto-purge and retention settings for one mailbox. Admins see any mailbox. Users are limited to owned mailboxes.
PUT
/admin/api/mailboxes/{address}/settings Payload and response
Updates mailbox trash auto-purge and retention behavior. Super-admin only.
POST
/admin/api/mailboxes/{address}/owners Payload and response
Adds owners to an existing mailbox. Admin or super-admin.
DELETE
/admin/api/mailboxes/{address}/owners Payload and response
Removes owners from an existing mailbox while enforcing minimum-owner rules. Admin or super-admin.
GET
/admin/api/mailboxes/{address}/forwarding Payload and response
Returns forwarding state, keep-copy behavior, and verified targets for a mailbox. Admins see any mailbox. Users are limited to owned mailboxes.
PUT
/admin/api/mailboxes/{address}/forwarding Payload and response
Enables or disables forwarding and controls whether the mailbox keeps a local copy. Admins can update any mailbox. Users are limited to owned mailboxes.
GET
/admin/api/mailboxes/{address}/forwarding-targets Payload and response
Lists the external forwarding targets attached to a mailbox. Admins see any mailbox. Users are limited to owned mailboxes.
POST
/admin/api/mailboxes/{address}/forwarding-targets Payload and response
Adds external forwarding targets and sends verification emails. Admins can update any mailbox. Users are limited to owned mailboxes.
DELETE
/admin/api/mailboxes/{address}/forwarding-targets Payload and response
Removes forwarding targets from a mailbox. Admins can update any mailbox. Users are limited to owned mailboxes.
PUT
/admin/api/aliases/{aliasAddress} Payload and response
Creates or updates an alias and its target mailbox list. Admin or super-admin.
DELETE
/admin/api/aliases/{aliasAddress} Payload and response
Deletes an alias. Admin or super-admin.
GET
/admin/api/aliases Payload and response
Lists aliases for the current site. Admin or super-admin.

Route examples

POST /admin/api/mailboxesCreate mailbox
Payload example
{
  "address": "support@example.com",
  "owners": ["user_123", "user_456"]
}
Response example
{
  "address": "support@example.com",
  "status": "ACTIVE",
  "owners": ["user_123", "user_456"]
}
GET /admin/api/mailboxesList mailboxes
Query example
{
  "limit": 25,
  "nextToken": "opaque-token"
}
Response example
{
  "items": [
    {
      "address": "support@example.com",
      "status": "ACTIVE",
      "owners": ["user_123", "user_456"]
    }
  ],
  "nextToken": "opaque-token"
}
PATCH /admin/api/mailboxes/{address}Replace mailbox owners
Payload example
{
  "owners": ["user_123", "user_789"]
}
Response example
{
  "address": "support@example.com",
  "status": "ACTIVE",
  "owners": ["user_123", "user_789"]
}
DELETE /admin/api/mailboxes/{address}Disable mailbox
Path example
{
  "address": "support@example.com"
}
Response

Returns 204 No Content on success.

POST /admin/api/mailboxes/{address}/purgePermanently purge mailbox
Payload example
{
  "confirm": true
}
Response

Returns 204 No Content on success.

POST /admin/api/mailboxes/{address}/restoreRestore mailbox
Payload example
{
  "owners": ["user_123", "user_456"]
}
Response example
{
  "address": "support@example.com",
  "status": "ACTIVE",
  "owners": ["user_123", "user_456"]
}
GET /admin/api/mailboxes/{address}/settingsRead mailbox settings
Path example
{
  "address": "support@example.com"
}
Response example
{
  "mailbox": "support@example.com",
  "trashAutoPurge": true,
  "trashRetentionDays": 30
}
PUT /admin/api/mailboxes/{address}/settingsUpdate mailbox settings
Payload example
{
  "trashAutoPurge": true,
  "trashRetentionDays": 30
}
Response example
{
  "mailbox": "support@example.com",
  "trashAutoPurge": true,
  "trashRetentionDays": 30
}
POST /admin/api/mailboxes/{address}/ownersAdd owners
Payload example
{
  "owners": ["user_789"]
}
Response example
{
  "address": "support@example.com",
  "status": "ACTIVE",
  "owners": ["user_123", "user_456", "user_789"]
}
DELETE /admin/api/mailboxes/{address}/ownersRemove owners
Payload example
{
  "owners": ["user_456"]
}
Response example
{
  "address": "support@example.com",
  "status": "ACTIVE",
  "owners": ["user_123"]
}
GET /admin/api/mailboxes/{address}/forwardingRead forwarding state
Path example
{
  "address": "support@example.com"
}
Response example
{
  "mailbox": "support@example.com",
  "enabled": true,
  "keepCopy": true,
  "targets": [
    {
      "target": "person@gmail.com",
      "status": "VERIFIED"
    }
  ]
}
PUT /admin/api/mailboxes/{address}/forwardingUpdate forwarding state
Payload example
{
  "enabled": true,
  "keepCopy": true
}
Response example
{
  "mailbox": "support@example.com",
  "enabled": true,
  "keepCopy": true,
  "targets": []
}
GET /admin/api/mailboxes/{address}/forwarding-targetsList forwarding targets
Path example
{
  "address": "support@example.com"
}
Response example
{
  "mailbox": "support@example.com",
  "items": [
    {
      "target": "person@gmail.com",
      "status": "VERIFIED",
      "createdAt": "2026-03-20T15:00:00.000Z"
    }
  ]
}
POST /admin/api/mailboxes/{address}/forwarding-targetsAdd forwarding targets
Payload example
{
  "targets": ["person@gmail.com"]
}
Response example
{
  "mailbox": "support@example.com",
  "items": [
    {
      "target": "person@gmail.com",
      "status": "PENDING",
      "verificationSent": true
    }
  ]
}
DELETE /admin/api/mailboxes/{address}/forwarding-targetsRemove forwarding targets
Payload example
{
  "targets": ["person@gmail.com"]
}
Response

Returns 204 No Content on success.

PUT /admin/api/aliases/{aliasAddress}Create or update alias
Payload example
{
  "targets": ["support@example.com", "sales@example.com"]
}
Response example
{
  "address": "hello@example.com",
  "targets": ["support@example.com", "sales@example.com"]
}
DELETE /admin/api/aliases/{aliasAddress}Delete alias
Path example
{
  "aliasAddress": "hello@example.com"
}
Response

Returns 204 No Content on success.

GET /admin/api/aliasesList aliases
Request

No request body.

Response example
{
  "items": [
    {
      "address": "hello@example.com",
      "targets": ["support@example.com", "sales@example.com"]
    }
  ]
}

Messages

Method Path Purpose Access
GET
/admin/api/messages Payload and response
Lists messages by mailbox, folder, and optional time window, with pagination support. Admins see any mailbox. Users are limited to owned mailboxes.
GET
/admin/api/messages/{messageId} Payload and response
Reads message metadata and returns signed URLs for attachments and raw message content. Admins see any mailbox. Users are limited to owned mailboxes.
DELETE
/admin/api/messages/{messageId} Payload and response
Soft-deletes a message by moving it to Trash, or marks it deleted when already in Trash. Admins see any mailbox. Users are limited to owned mailboxes.
POST
/admin/api/messages/attachments Payload and response
Stages an outbound attachment upload and returns an attachment token for send or reply requests. Mailbox access rules apply.
POST
/admin/api/messages/send Payload and response
Sends a new outbound message through the shared SMTP gateway from a site mailbox. Mailbox access rules apply.
POST
/admin/api/messages/{messageId}/reply Payload and response
Loads reply context for the parent message and sends the reply through the shared SMTP gateway. Mailbox access rules apply.
POST
/admin/api/messages/{messageId}/restore Payload and response
Restores a message from Trash back to its original folder, or to Inbox when needed. Mailbox access rules apply.
POST
/admin/api/messages/{messageId}/archive Payload and response
Moves a message into Archive. Mailbox access rules apply.
POST
/admin/api/messages/{messageId}/seen Payload and response
Marks a message seen or unseen for mailbox client state. Mailbox access rules apply.
POST
/admin/api/messages/{messageId}/purge Payload and response
Hard-deletes one message and its stored objects immediately. Super-admin only.
POST
/admin/api/messages/purge Payload and response
Hard-deletes a selected list of message IDs in one request. Super-admin only.
POST
/admin/api/messages/purge-deleted Payload and response
Hard-deletes deleted messages that match the supplied site-scoped filters. Super-admin only.
POST
/admin/api/messages/purge-all Payload and response
Hard-deletes all deleted messages for the current site. Super-admin only.

Route examples

GET /admin/api/messagesList messages
Query example
{
  "mailbox": "support@example.com",
  "folder": "INBOX",
  "limit": 25,
  "nextToken": "opaque-token",
  "includeDeleted": false
}
Response example
{
  "items": [
    {
      "id": "msg_123",
      "mailbox": "support@example.com",
      "folder": "INBOX",
      "subject": "Question about pricing",
      "hasAttachments": false,
      "seen": false
    }
  ],
  "nextToken": "opaque-token"
}
GET /admin/api/messages/{messageId}Read message detail
Path example
{
  "messageId": "msg_123"
}
Response example
{
  "id": "msg_123",
  "mailbox": "support@example.com",
  "folder": "INBOX",
  "from": "customer@example.org",
  "to": ["support@example.com"],
  "subject": "Question about pricing",
  "attachments": [],
  "rawUrl": "https://signed-url",
  "seen": false
}
DELETE /admin/api/messages/{messageId}Soft-delete message
Path example
{
  "messageId": "msg_123"
}
Response

Returns 204 No Content on success.

POST /admin/api/messages/attachmentsStage attachment upload
Payload example
{
  "mailbox": "support@example.com",
  "filename": "invoice.pdf",
  "contentType": "application/pdf",
  "size": 102400
}
Response example
{
  "attachmentRef": "<opaque-token>",
  "mailbox": "support@example.com",
  "filename": "invoice.pdf",
  "contentType": "application/pdf",
  "size": 102400,
  "upload": {
    "method": "PUT",
    "url": "https://signed-upload",
    "headers": {
      "Content-Type": "application/pdf"
    },
    "expiresAt": "2025-11-12T04:45:00Z"
  }
}

Use this staged upload flow for browser and admin UI clients. Server-side callers should use Hydrix.sendEmail(...) or direct SMTP submission with inline attachments[] or base64 raw. Limits: 10 attachments max, 10 MiB per file, 15 MiB total decoded attachment bytes, and a 25 MiB shared-gateway raw message cap. The upload target is a presigned S3 PUT; expect a normal S3 success status, typically HTTP 200, with no JSON body. Uploads are CORS-ready from the admin origin. attachmentRef values are reusable until expiry while the staged object still exists, but successful send/reply deletes the staged upload.

POST /admin/api/messages/sendSend new message
Payload example
{
  "mailbox": "support@example.com",
  "to": ["customer@example.org"],
  "subject": "Reaching out",
  "body": "Hello from Hydrix.",
  "attachmentRefs": ["<opaque-token>"]
}
Response example
{
  "id": "msg_456",
  "threadId": "thread_123"
}

The response confirms gateway acceptance. Sent items usually appear on the next message or thread fetch immediately, but clients should still use optimistic UI and tolerate brief eventual consistency before a refresh reflects the new message.

POST /admin/api/messages/{messageId}/replyReply to message
Payload example
{
  "body": "Thanks for reaching out.",
  "subject": "Re: Question about pricing",
  "attachmentRefs": ["<opaque-token>"]
}
Response example
{
  "id": "msg_789",
  "threadId": "thread_123"
}

The response confirms gateway acceptance. Reply messages usually appear on the next message or thread fetch immediately, but clients should still use optimistic UI and tolerate brief eventual consistency before a refresh reflects the new reply.

POST /admin/api/messages/{messageId}/restoreRestore message
Path example
{
  "messageId": "msg_123"
}
Response example
{
  "id": "msg_123",
  "deleted": false
}
POST /admin/api/messages/{messageId}/archiveArchive message
Path example
{
  "messageId": "msg_123"
}
Response

Returns 204 No Content on success.

POST /admin/api/messages/{messageId}/seenMark seen or unseen
Payload example
{
  "seen": true
}
Response example
{
  "id": "msg_123",
  "seen": true
}
POST /admin/api/messages/{messageId}/purgePurge one message
Path example
{
  "messageId": "msg_123"
}
Response

Returns 204 No Content on success.

POST /admin/api/messages/purgeBulk purge selected messages
Payload example
{
  "messageIds": ["msg_123", "msg_456"],
  "force": true
}
Response example
{
  "purged": ["msg_123", "msg_456"],
  "failed": []
}
POST /admin/api/messages/purge-deletedPurge deleted by filter
Payload example
{
  "confirm": true,
  "dryRun": false,
  "filters": {
    "mailbox": "support@example.com"
  }
}
Response example
{
  "matchedCount": 12,
  "deletedCount": 12,
  "failedCount": 0,
  "dryRun": false
}
POST /admin/api/messages/purge-allPurge all deleted messages
Payload example
{
  "confirm": true,
  "dryRun": false
}
Response example
{
  "matchedCount": 42,
  "deletedCount": 42,
  "failedCount": 0,
  "dryRun": false
}

Contact and Site Settings

Method Path Purpose Access
GET
/admin/api/contact-recipients Payload and response
Lists the site-local recipients that receive /admin/public/contact submissions. Admin or super-admin.
POST
/admin/api/contact-recipients Payload and response
Adds site-local contact-form recipients. Admin or super-admin.
DELETE
/admin/api/contact-recipients Payload and response
Removes contact-form recipients. Admin or super-admin.
GET
/admin/api/auth-email-branding Payload and response
Reads site-specific Cognito auth-email branding for the admin and data-system pools. Super-admin only.
PUT
/admin/api/auth-email-branding Payload and response
Creates, updates, or clears auth-email branding for the admin and data-system pools. Super-admin only.
POST
/admin/api/super-admin-invites/resend Payload and response
Reissues pending super-admin invites and rotates their onboarding tokens. Super-admin only.

Route examples

GET /admin/api/contact-recipientsList contact recipients
Request

No request body.

Response example
{
  "items": [
    {
      "email": "contact@example.com",
      "createdAt": "2026-03-20T15:00:00.000Z",
      "updatedAt": "2026-03-20T15:00:00.000Z"
    }
  ]
}
POST /admin/api/contact-recipientsAdd contact recipients
Payload example
{
  "recipients": ["contact@example.com", "sales@example.com"]
}
Response example
{
  "items": [
    {
      "email": "contact@example.com"
    },
    {
      "email": "sales@example.com"
    }
  ]
}
DELETE /admin/api/contact-recipientsRemove contact recipients
Payload example
{
  "recipients": ["sales@example.com"]
}
Response

Returns 204 No Content on success.

GET /admin/api/auth-email-brandingRead auth email branding
Request

No request body.

Response example
{
  "siteId": "site_123",
  "authEmailBranding": {
    "adminVerificationEmail": {
      "subject": "Your admin code",
      "htmlBody": "<p>Your code is <strong>{{code}}</strong>.</p>"
    }
  },
  "messageTypes": ["adminVerificationEmail", "dataVerificationEmail"]
}
PUT /admin/api/auth-email-brandingSave auth email branding
Payload example
{
  "adminVerificationEmail": {
    "subject": "Your admin code",
    "htmlBody": "<p>Your code is <strong>{{code}}</strong>.</p>"
  },
  "dataVerificationEmail": null
}
Response example
{
  "siteId": "site_123",
  "authEmailBranding": {
    "adminVerificationEmail": {
      "subject": "Your admin code",
      "htmlBody": "<p>Your code is <strong>{{code}}</strong>.</p>"
    }
  }
}
POST /admin/api/super-admin-invites/resendResend super-admin invites
Payload example
{
  "superAdminEmails": ["owner@example.com"]
}
Response example
{
  "matchedCount": 1,
  "resentCount": 1,
  "status": "sent"
}

/admin/data Routes

These routes manage the site data runtime. They are always authenticated with the site admin pool and are intended for admins or super-admins. Resource and runtime provisioning can be asynchronous, so callers should treat provisioning and retryable availability states as part of the normal contract.

Resources and Operation Bindings

Method Path Purpose Access
POST
/admin/data/resources Payload and response
Creates a data resource such as a DynamoDB table, S3 bucket, or Lambda-backed runtime helper. Admin or super-admin.
GET
/admin/data/resources Payload and response
Lists current resources and operation bindings. This route can return provisioning status while runtime boots. Admin or super-admin.
PATCH
/admin/data/resources/{resourceId} Payload and response
Updates one resource’s metadata or runtime configuration. Admin or super-admin.
DELETE
/admin/data/resources/{resourceId} Payload and response
Deletes one resource from the site data runtime. Admin or super-admin.
POST
/admin/data/resources/{resourceId}/data/ddb/{action} Payload and response
Runs a direct DynamoDB helper against a bound resource. Supported actions are get, query, scan, put, update, and delete. Admin or super-admin.
POST
/admin/data/resources/{resourceId}/data/s3/{action} Payload and response
Runs a direct S3 helper against a bound resource. Supported actions are list-objects, get-object, put-object, delete-object, presign-get-object, and presign-put-object. Admin or super-admin.
POST
/admin/data/operations Payload and response
Creates or updates a site data operation binding, either to a Lambda resource or to a built-in preset. Admin or super-admin.
DELETE
/admin/data/operations/{operation} Payload and response
Deletes one site data operation binding. Admin or super-admin.
POST
/admin/data/operations/{operation} Payload and response
Invalidates cached responses for one data operation. Admin or super-admin.
POST
/admin/data/reconcile Payload and response
Repairs data runtime first, then queues reconcile once runtime is ready to realign runtime and control state. Admin or super-admin.

Route examples

POST /admin/data/resourcesCreate resource
Payload example
{
  "type": "ddbTable",
  "name": "profiles",
  "config": {
    "partitionKey": {
      "name": "pk",
      "type": "S"
    }
  }
}
Response example
{
  "resourceId": "res_profiles",
  "type": "ddbTable",
  "name": "profiles",
  "permissionsSync": {
    "status": "queued"
  }
}
GET /admin/data/resourcesList resources and bindings
Request

No request body.

Response example
{
  "resources": [
    {
      "resourceId": "res_profiles",
      "type": "ddbTable",
      "name": "profiles"
    }
  ],
  "operations": []
}
PATCH /admin/data/resources/{resourceId}Update resource metadata
Payload example
{
  "name": "profiles-v2",
  "config": {
    "ttlAttribute": "expiresAt"
  }
}
Response example
{
  "resourceId": "res_profiles",
  "type": "ddbTable",
  "name": "profiles-v2"
}
DELETE /admin/data/resources/{resourceId}Delete resource
Path example
{
  "resourceId": "res_profiles"
}
Response example
{
  "ok": true
}
POST /admin/data/resources/{resourceId}/data/ddb/{action}Direct DynamoDB helper
Payload example
{
  "key": {
    "pk": "user#123"
  }
}
Response example
{
  "item": {
    "pk": "user#123",
    "name": "Ada"
  }
}
POST /admin/data/resources/{resourceId}/data/s3/{action}Direct S3 helper
Payload example
{
  "prefix": "uploads/",
  "maxKeys": 25
}
Response example
{
  "items": [
    {
      "key": "uploads/example.txt"
    }
  ]
}
POST /admin/data/operationsCreate or update operation binding
Payload example
{
  "operation": "getProfile",
  "lambdaResourceId": "res_profiles_handler",
  "auth": {
    "mode": "authenticated"
  },
  "cache": {
    "ttlSeconds": 60
  }
}
Response example
{
  "operation": "getProfile",
  "resourceId": "res_profiles_handler",
  "permissionsSync": {
    "status": "queued"
  }
}
DELETE /admin/data/operations/{operation}Delete operation binding
Path example
{
  "operation": "getProfile"
}
Response example
{
  "ok": true
}
POST /admin/data/operations/{operation}Invalidate cached operation output
Path example
{
  "operation": "getProfile"
}
Response example
{
  "ok": true,
  "invalidatedCount": 3
}
POST /admin/data/reconcileRepair data system
Request

No request body.

Response example
{
  "status": "queued",
  "permissionsSync": {
    "status": "queued"
  }
}

Jobs, Groups, Env Vars, and Compute

Method Path Purpose Access
GET
/admin/data/jobs Payload and response
Lists configured backend jobs for the site data runtime. Admin or super-admin.
PUT
/admin/data/jobs/{jobId} Payload and response
Creates or updates a backend job, including schedule, payload, and auth context. Admin or super-admin.
POST
/admin/data/jobs/{jobId} Payload and response
Runs one configured backend job immediately. Admin or super-admin.
DELETE
/admin/data/jobs/{jobId} Payload and response
Deletes one backend job and any attached schedule. Admin or super-admin.
GET
/admin/data/groups Payload and response
Lists data-system Cognito groups used to protect authenticated data operations. Admin or super-admin.
POST
/admin/data/groups Payload and response
Creates a data-system Cognito group. Admin or super-admin.
DELETE
/admin/data/groups/{groupName} Payload and response
Deletes a data-system Cognito group. Admin or super-admin.
POST
/admin/data/groups/{groupName}/users Payload and response
Adds a data-system user to one group. Admin or super-admin.
DELETE
/admin/data/groups/{groupName}/users Payload and response
Removes a data-system user from one group. Admin or super-admin.
GET
/admin/data/env-vars Payload and response
Lists site env vars. Secret values remain write-only and are never returned. Admin or super-admin.
PUT
/admin/data/env-vars Payload and response
Creates or updates site env vars in secure storage. Admin or super-admin.
DELETE
/admin/data/env-vars Payload and response
Deletes all current site env vars. Admin or super-admin.
POST
/admin/data/compute/execute Payload and response
Runs ad hoc CommonJS code inside the tenant-isolated compute runner. Admin or super-admin.

Route examples

GET /admin/data/jobsList jobs
Request

No request body.

Response example
{
  "items": [
    {
      "jobId": "nightly-sync",
      "operation": "syncProfiles"
    }
  ]
}
PUT /admin/data/jobs/{jobId}Create or update job
Payload example
{
  "operation": "syncProfiles",
  "payload": {
    "full": true
  },
  "schedule": {
    "cron": "0 2 * * *"
  }
}
Response example
{
  "jobId": "nightly-sync",
  "operation": "syncProfiles",
  "schedule": {
    "cron": "0 2 * * *"
  }
}
POST /admin/data/jobs/{jobId}Run job now
Payload example
{
  "trigger": "manual"
}
Response example
{
  "ok": true,
  "data": {
    "jobId": "nightly-sync",
    "status": "started"
  }
}
DELETE /admin/data/jobs/{jobId}Delete job
Path example
{
  "jobId": "nightly-sync"
}
Response example
{
  "ok": true
}
GET /admin/data/groupsList data groups
Request

No request body.

Response example
{
  "items": [
    {
      "groupName": "members",
      "description": "Authenticated members"
    }
  ]
}
POST /admin/data/groupsCreate data group
Payload example
{
  "groupName": "members",
  "description": "Authenticated members"
}
Response example
{
  "groupName": "members",
  "description": "Authenticated members"
}
DELETE /admin/data/groups/{groupName}Delete data group
Path example
{
  "groupName": "members"
}
Response example
{
  "ok": true
}
POST /admin/data/groups/{groupName}/usersAdd user to group
Payload example
{
  "username": "visitor@example.com"
}
Response example
{
  "groupName": "members",
  "username": "visitor@example.com",
  "ok": true
}
DELETE /admin/data/groups/{groupName}/usersRemove user from group
Payload example
{
  "username": "visitor@example.com"
}
Response example
{
  "groupName": "members",
  "username": "visitor@example.com",
  "ok": true
}
GET /admin/data/env-varsList env vars
Request

No request body.

Response example
{
  "items": [
    {
      "name": "API_BASE_URL",
      "secret": false,
      "value": "https://api.example.com"
    }
  ]
}
PUT /admin/data/env-varsSave env vars
Payload example
{
  "storageBackend": "ssmSecureString",
  "variables": {
    "API_BASE_URL": {
      "value": "https://api.example.com"
    },
    "API_SECRET": {
      "value": "secret-value",
      "secret": true
    }
  }
}
Response example
{
  "items": [
    {
      "name": "API_BASE_URL",
      "secret": false
    },
    {
      "name": "API_SECRET",
      "secret": true
    }
  ]
}
DELETE /admin/data/env-varsDelete env vars
Request

No request body.

Response example
{
  "ok": true
}
POST /admin/data/compute/executeRun compute snippet
Payload example
{
  "code": "module.exports = async ({ payload }) => ({ echoed: payload });",
  "payload": {
    "hello": "world"
  },
  "timeoutSeconds": 10
}
Response example
{
  "ok": true,
  "data": {
    "echoed": {
      "hello": "world"
    }
  }
}

IaC Jobs and Saved Definitions

Method Path Purpose Access
POST
/admin/data/iac/jobs Payload and response
Submits an asynchronous IaC apply or replace job for resources, operations, jobs, groups, and env vars. Admin or super-admin.
GET
/admin/data/iac/jobs Payload and response
Lists async IaC jobs for the current site. Admin or super-admin.
GET
/admin/data/iac/jobs/{jobId} Payload and response
Reads the status, summary, and permissions-sync state for one IaC job. Admin or super-admin.
GET
/admin/data/iac/definitions Payload and response
Lists saved IaC definition profiles for the current site organization. Admin or super-admin.
GET
/admin/data/iac/definitions/{profileName} Payload and response
Reads one saved IaC definition profile. Admin or super-admin.
PUT
/admin/data/iac/definitions/{profileName} Payload and response
Creates or updates one saved IaC definition profile. Admin or super-admin.
DELETE
/admin/data/iac/definitions/{profileName} Payload and response
Deletes one saved IaC definition profile. Admin or super-admin.

Route examples

POST /admin/data/iac/jobsSubmit IaC job
Payload example
{
  "mode": "apply",
  "definitionProfileName": "baseline",
  "persistDefinition": false,
  "definition": {
    "resources": [
      {
        "type": "ddbTable",
        "name": "profiles"
      }
    ]
  }
}
Response example
{
  "jobId": "iac_job_123",
  "status": "queued",
  "definitionSource": "inline",
  "definitionPersisted": false
}
GET /admin/data/iac/jobsList IaC jobs
Request

No request body.

Response example
{
  "items": [
    {
      "jobId": "iac_job_123",
      "status": "running",
      "definitionSource": "profile"
    }
  ]
}
GET /admin/data/iac/jobs/{jobId}Read IaC job
Path example
{
  "jobId": "iac_job_123"
}
Response example
{
  "jobId": "iac_job_123",
  "status": "succeeded",
  "definitionSource": "profile",
  "permissionsSync": {
    "status": "queued"
  }
}
GET /admin/data/iac/definitionsList saved definitions
Request

No request body.

Response example
{
  "items": [
    {
      "profileName": "baseline",
      "updatedAt": "2026-03-20T15:00:00.000Z"
    }
  ]
}
GET /admin/data/iac/definitions/{profileName}Read saved definition
Path example
{
  "profileName": "baseline"
}
Response example
{
  "profileName": "baseline",
  "definition": {
    "resources": [
      {
        "type": "ddbTable",
        "name": "profiles"
      }
    ]
  }
}
PUT /admin/data/iac/definitions/{profileName}Save definition
Payload example
{
  "definition": {
    "resources": [
      {
        "type": "ddbTable",
        "name": "profiles"
      }
    ]
  },
  "overwriteDefinition": true
}
Response example
{
  "profileName": "baseline",
  "definition": {
    "resources": [
      {
        "type": "ddbTable",
        "name": "profiles"
      }
    ]
  }
}
DELETE /admin/data/iac/definitions/{profileName}Delete definition
Path example
{
  "profileName": "baseline"
}
Response example
{
  "ok": true
}

/data Routes

The site Data API has only four site-facing route shapes. The concrete operation name after /data/ is site-defined and comes from the operation bindings you create under /admin/data/operations.

Method Path Purpose Access
GET
/data/auth/config Payload and response
Returns data-system auth discovery: user pool, client ID, issuer, region, and optional Hosted UI or localhost-dev settings. No token.
GET
/data/public/auth/config Payload and response
Public alias for the same auth-discovery response as /data/auth/config. No token.
POST
/data/public/{operation} Payload and response
Calls a public site data operation with no visitor authentication. No token.
POST
/data/{operation} Payload and response
Calls an authenticated site data operation with a data-system access token. Data-system access token.

Route examples

GET /data/auth/configVisitor auth discovery
Request

No request body.

Response example
{
  "ok": true,
  "data": {
    "enabled": true,
    "userPoolId": "us-east-1_example",
    "userPoolClientId": "123exampleclient",
    "issuer": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_example",
    "region": "us-east-1",
    "domain": "https://hydrix-data-example.auth.us-east-1.amazoncognito.com",
    "providers": {
      "google": {
        "enabled": true,
        "identityProvider": "Google",
        "responseType": "code",
        "scopes": ["openid", "email", "profile", "aws.cognito.signin.user.admin"]
      }
    }
  }
}
GET /data/public/auth/configPublic auth discovery alias
Request

No request body.

Response example
{
  "ok": true,
  "data": {
    "enabled": true,
    "userPoolId": "us-east-1_example",
    "userPoolClientId": "123exampleclient",
    "issuer": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_example",
    "region": "us-east-1"
  }
}
POST /data/public/{operation}Public data operation
Payload example
{
  "payload": {
    "pk": "user#123"
  }
}
Response example
{
  "ok": true,
  "data": {
    "pk": "user#123",
    "name": "Ada"
  }
}
POST /data/{operation}Authenticated data operation
Payload example
{
  "payload": {
    "pk": "user#123"
  }
}
Response example
{
  "ok": true,
  "data": {
    "pk": "user#123",
    "name": "Ada"
  }
}

Request Shape

  • Send JSON with a top-level payload field.
  • The runtime also receives request metadata and derived auth context.
  • Use POST for every data operation route.

Response Envelope

  • { "ok": true, "data": ... } on success
  • { "ok": false, "error": { "code": "...", "message": "..." } } on failure
  • Downstream provider details are sanitized before reaching the browser.

Token Validation

  • token_use must be access.
  • iss, client_id, and exp must match the discovered site config.
  • A localhost dev client is also accepted when the site exposes one in auth discovery.
  • When Google discovery is present, use providers.google.scopes exactly as returned, including aws.cognito.signin.user.admin.