Exchange is excluded from this API/CLI release. Any historical Exchange API or CLI example in this guide is unavailable; native portal behavior is outside this exclusion. See [current release scope](/developers/guides/release-scope?lang=en).

# Team invitations: authority, delivery and recovery

Portal login is now passkey-only. Existing password users and new customers start with an email link and enroll their first passkey before access. See [passkey setup, migration and recovery](/developers/guides/passkeys?lang=en). Browser OAuth uses the same login; existing scopes and permissions remain enforced.

Company and member policy flags cannot re-enable password login. Passkeys are mandatory for everyone; a verified passkey satisfies the former MFA setup requirement.

The portal and `POST /api/v1/accounts/{account}/team/invitations` create member invitations through the same company permission policy. API callers need `team:write` and a current human grant with recent strong verification. The portal uses the current company, browser identity and existing passkey/authenticator verification. A service connection cannot issue this capability.

`POST /api/v1/accounts/{account}/team/invitations/{id}/resend` replaces an existing pending invitation's acceptance token. The portal's resend button uses the same policy. Creating an invitation cannot request the owner role. A previously stored owner invitation, including a legacy row with `permissions: null`, can be resent or revoked only by a **current owner of that company**. Seeing `role: owner` in a read response conveys no permission to act on it. A delegated team manager can invite or resend a normal member only within the manager's current module permissions; a read permission cannot become write permission.

The invitation token is a private capability. List/create/resend API responses and audit metadata never return it. Acceptance happens through the explicit browser workflow in the recipient's email. Links use the configured canonical portal origin, independently of the incoming request Host.

Before creating or rotating a token, delivery requires a configured single credential-safe SMTP or sendmail transport. SMTP requires TLS and certificate verification. Log, failover and round-robin transports are refused. A global mail debug recipient cannot redirect the invitation. Only the exact invitation recipient receives the message; CC and BCC recipients are refused.

The server keeps the original actor, authentication epoch, company, invitation contents and transport source bound during delivery. It rechecks current company status, membership, delegation ceiling, invitation state, original API grant or browser session and strong-authentication policy after rendering the message. The final clock check runs after those policy reads and immediately before handing the message to the maintained mail transport. Expired verification produces the portal's existing verification guidance. Changed or withdrawn authority prevents delivery.

The invitation and its original API operation are committed before SMTP submission. A successful synchronous response confirms transport acceptance, **not inbox delivery**. The API retains the invitation ID and an unconfirmed-mail marker when submission is not confirmed. An SMTP timeout or lost acknowledgement may mean the recipient already received the email. The server does not automatically retry or fall back to another transport; the response uses `invitation_delivery_unconfirmed` without raw SMTP/debug details.

For users and AI agents after an uncertain result:

1. Keep the original company, numeric invitation ID and API operation ID or idempotency key. Read the original operation and invitation list; do not invent a replacement operation or claim inbox delivery.
2. Repeating an API request with its original failed key does not send another email. A pending invitation still belongs to the original company and recipient.
3. If another delivery is required after review, use the explicit resend action with current authority and recent verification. Resend replaces the old acceptance link. A delegated member still cannot resend a legacy owner invitation.

`TeamInvitationDeliverySecurityTest` verifies both portal and API paths using captured mail, actual rendered messages and a private loopback TLS SMTP sink. It covers delegation and legacy owner boundaries, withdrawal during rendering, epoch/session/grant/scope changes, expiry, recipient/token/source changes, forbidden transports, exact recipients despite debug configuration, and lost SMTP acknowledgements without automatic second delivery. These tests send no customer email and do not change system certificate trust.
