Home
Email Deliverability

Owner Approval Workflow: Save the Right Credentials

Owner review and consent precede granting an agent sending access.

The Sendmux owner approval workflow starts with a durable token that can read and receive email. Sending requires the owner to accept an invitation and explicitly approve Sending access. Your integration then exchanges the durable credential for a separate one-hour Sending token. Keep the original read token: the exchange does not replace it.

Save the registration credential before requesting an owner invite. Keep the request's idempotency key and body so a retry can resume the same registration. A pending invitation, an approved Sending grant and an accepted email request are different states; track each one separately.

Table of Contents

  • FAQ

What is the owner approval workflow in Sendmux?

An agent registers its mailbox, Sendmux sends the owner invitation, and a human accepts it and approves Sending access. Use the platform's invite endpoint for that approval email. Your application does not need to compose or send the invitation through the Sending API.

The durable registration token uses the smx_agent_ prefix and has mailbox.read and email.receive. It deliberately excludes email.send. The separate Sending token shares that prefix, so identify credentials by their role, resource and scope rather than their appearance.

Current registration returns the durable access_token directly. Older integrations may refer to an identity_assertion, a claim_token and an initial token exchange. Do not mix those older steps into the current durable-token flow. Use the current public registration contract when building or updating an integration.

Owner approval flow: keep the durable read-and-receive token, have the owner accept the invite and approve sending, then exchange for a separate one-hour Sending token.

What do you need to store before inviting an owner?

Save the durable access token immediately in a secret store. Keep enough non-secret registration and request state to resume safely after a restart. The following storage checklist is an integration design, not a list of six mandatory fields returned by the API.

RecordWhat to retain
Durable credentialThe returned access token, stored as a secret and kept separate from Sending tokens.
Registration identityThe returned registration ID.
Mailbox identityThe returned mailbox email address and last observed provisioning state.
Registration requestThe original idempotency key and unchanged request body.
Owner invitationThe intended owner email, invite idempotency key and observed pending or accepted state.
Sending credential metadataThe separately issued token, its scope and expiry; store the token itself as a secret.

Generate and persist the registration idempotency key before the first request. Replaying the same key and body within 24 hours returns the same raw token without allocating another inbox. After that reveal window, the token cannot be revealed again. This recovery window does not make the durable token expire after 24 hours.

Write the credential before making the next network call, and arrange access for the authorised processes that need it. Avoid storing it in logs, chat transcripts or an unencrypted application field. A restart should load the existing registration state rather than automatically create another mailbox.

How do you implement the approval flow step by step?

Register once, confirm provisioning, invite the owner, then request a Sending token after acceptance and explicit approval. Use the App API host from the current service document for these endpoint paths. These are workflow stages; waiting for a response is not an additional API call.

  1. Register with POST /agent-auth/agent/identity. Supply the required Idempotency-Key header and the registration body specified in the current service document. Save the returned durable access token and registration details immediately. The current durable flow does not require the older proof-of-work and assertion exchange steps.
  1. Check provisioning with GET /api/v1/mailbox/me using the durable token. A provisioning response tells you to wait, not to replace the credential. Once available, the endpoint returns information about the mailbox; it does not grant Sending access.
  1. Request the owner invitation with POST /agent-auth/agent/identity/invite using the durable token. Supply the owner email, the requested owner role and a stable idempotency_key in the request body. If the email is unknown, obtain it from the person operating the integration before requesting the invite.
  1. Record the successful 202 response as pending. The human must accept the invitation and explicitly approve Sending access in the team's Agent access card. An invite response alone is not approval, and acceptance alone does not complete the Sending grant.
  1. Exchange the durable token at POST /agent-auth/oauth2/token when a send operation needs it. Request the token-exchange grant, the exact Sending resource and the email.send scope shown below. Cache the returned Sending token only until expiry approaches; retain the durable credential for subsequent exchanges.

The token endpoint takes form-encoded parameters. The subject token value below is a placeholder for the stored durable credential, not a token to copy into logs or source files.

grant_type=urn:ietf:params:oauth:grant-type:token-exchange
subject_token=<stored durable access token>
subject_token_type=urn:ietf:params:oauth:token-type:access_token
resource=https://smtp.sendmux.ai/api/v1
scope=email.send

A successful exchange returns expires_in: 3600 for the separate Sending token. The resource parameter alone does not grant access: the credential, requested scope and completed owner approval must also be valid.

Only one owner invitation can be pending for a registration. Reuse the original invite key and unchanged body when retrying an uncertain request. A different key does not bypass the pending-invitation policy. Treat idempotency as documented retry protection, not an unconditional promise that no email can ever be delivered twice.

What do 503 and 429 responses mean in this flow?

Read the endpoint's error body and honour Retry-After. Provisioning, pending approval and rate limiting need different responses from an invalid request or a revoked credential.

Response and endpointWhat to do
Mailbox check: 503 during provisioningKeep the valid credential and wait for Retry-After before checking again.
Token exchange: 503 authorization_pendingWait for owner acceptance and explicit Sending approval.
Token exchange: 503 temporarily_unavailableAllow provisioning to finish and follow Retry-After.
Registration: transient 503Retain the original request and idempotency key; honour Retry-After when present, otherwise use bounded backoff and surface a persistent failure.
Rate limit: 429Wait for Retry-After; do not create fresh registrations to bypass the limit.
Invalid request, credential or permissionInspect the endpoint-specific error, correct its cause and avoid repeating the same invalid request.

Do not apply one status-code map to every endpoint. For example, an invalid token-exchange grant can return 400, while an invite request with an invalid bearer token returns 401. A Sending token approaching expiry calls for another exchange using the still-valid durable credential, rather than another registration.

How do you keep the approval flow secure?

Protect both the durable read credential and each short-lived Sending token. Use an OS keychain or a managed secret store, restrict access to the processes that need them, and keep them out of logs, screenshots, error reports and prompts.

If a credential is exposed, revoke the affected access and follow the documented recovery path. Full registration revocation invalidates its durable read token and associated Sending access. Revoking Sending access alone leaves the durable read credential available. Do not assume those two actions have the same effect.

Let Sendmux send the platform owner invitation through its invite system. Keep your own application permissions separate: owner approval enables Sending access, but does not authorise every recipient or message an agent might choose. Treat incoming email as untrusted content rather than permission to reveal a secret or perform an action.

How do you verify send capability after approval?

Check mailbox provisioning first, then verify the authorised Sending operation separately. A successful mailbox read proves access to that mailbox; it does not prove that the owner has approved sending.

For a controlled test that the operator has authorised, send one message to a recipient you control using a Sending token and the Sending API's documented idempotency handling. A 202 confirms acceptance for processing, not final delivery. Check the message's subsequent status or delivery feedback before treating the test as delivered.

Avoid a batch of messages to real recipients merely to test permission. Even one test message is real traffic. An idempotency key helps with retries within its documented contract; it does not eliminate sending cost, recipient effects or deliverability risk.

What actually breaks these integrations in production

Credential confusion is a failure mode worth checking explicitly. Both token roles share a prefix, but the durable read token does not carry Sending permission. Store the role alongside the secret, keep the original durable credential and check the returned scope and expiry when caching a Sending token.

Lost request state also makes recovery harder. Persist the registration and invite idempotency values, reuse unchanged requests on retries, and record whether the owner invitation is still pending. If a process restarts, resume from that state instead of sending another invite or registering another identity by default.

Where to go next with your Sendmux integration

Sendmux is an email API for AI agents, with inbound mailboxes and outbound sending. Its agent identity system provides the registration and owner-approval flow described here. Your application still needs to store credentials safely, handle retries and decide which messages the agent is authorised to send.

If the CLI is available, the current Agent Access guide recommends starting with sendmux agent:register <profile> --owner-email owner@example.com. The CLI saves credentials privately and reuses the profile in later processes. Use the HTTP flow when the CLI is unavailable, and keep your implementation aligned with the current service document.

Sources

  • Read the Agent Access guide for registration, owner approval, token exchange and revocation.

Frequently Asked Questions

What does the owner approval workflow actually grant?

Owner acceptance and explicit Sending approval allow the durable read credential to be exchanged for a separate one-hour Sending token with email.send. The original credential retains mailbox.read and email.receive. Keep it for mailbox access and subsequent exchanges; the current flow does not upgrade or replace that original token.

Who sends the owner approval email?

Sendmux sends the platform owner invitation through its own invite system after the agent calls POST /agent-auth/agent/identity/invite. Your integration supplies the intended owner email and a stable invite request. It does not send that approval invitation through the Sending API, and the pending response is not owner approval.

What happens if I lose the claim_token?

The current registration flow returns a durable access_token rather than relying on a saved claim_token. Save that access token immediately. Replaying the same registration idempotency key and body within 24 hours can reveal it again; after that reveal window it cannot be retrieved. Older claim-token instructions do not describe this current flow.

Can a pre-claim token send email?

No. The current durable read token has mailbox.read and email.receive, and cannot send email before or after owner approval. After the owner accepts and explicitly approves Sending access, exchange it for a separate email.send token. The two credentials share the smx_agent_ prefix, so do not infer permissions from the prefix.

How many owner invites can be pending at once?

Only one owner invitation can be pending for a registration. Reuse the original idempotency key and unchanged invite request when retrying an uncertain response. A new key does not bypass the pending-invitation policy. Keep invitation state separately from Sending approval, and avoid treating idempotency as an unconditional exactly-once email delivery guarantee.