Skip to main content
Prepare a credential, membership, managed identity/session or administrator invitation action for the initiating person to review in the authenticated browser. Preparation does not issue credentials, accept terms, or revoke existing keys. Use a verified personal MCP or Firebase identity; team API/OAuth keys cannot prepare these requests or impersonate their creator. Pass an authorized current team in the team query parameter for authentication context; team-scoped preparation should match body.team_id. Billing-account invitations instead require billing_account_id and no team_id; the query team is only authentication context. Reads and cancellation can use the selected current team even if the original credential team has changed. This does not change the credential mode.

Prepare an action

Save a UUIDv4 before the first request. This synthetic example prepares a live/test API key pair for a team with no active API keys:
Each new intended action needs its own saved UUID. A repeated preparation with the same creator, originating credential/mode, UUID and exact normalized input reads the same request. A changed payload returns 409 operation_conflict. After a preparation timeout, preserve and reuse the original ID and content; never generate a new ID as an automatic retry. A token name is trimmed and must contain 1–64 characters. Mode must be explicit. Unknown fields, caller-supplied authority and agent terms acceptance are rejected. A personal MCP token grants the user’s access across authorized teams; team_id is its initial context, not a security boundary limiting the resulting credential. The new token does not change the calling credential’s mode.

Membership scope

Membership actions require the current team owner using a verified personal identity. They affect access across production and test. requested_modes: [] means that no credential mode is being selected; it does not isolate the grant to test mode. The frozen membership_change shows the target account ID, email and name from Auth, previous role, current owner, and whether ownership changes. The target and owner must still be active, and changed identity, roster, permissions or account state requires a new review. Adding an admin is for an existing eligible user in the same billing account; use invitations for someone outside that account. Transfers keep the previous owner as an administrator and preserve billing-account ownership. No membership action issues an API key, password or login link.

Read and cancel

The response is HTTP 200 {success:true,data:approval,timestamp} with Cache-Control: no-store. It includes a 64-character lowercase approval id, operation_id, action, team identity, billing-account ID, normalized payload, requested modes, effect scope, status, millisecond timestamps and review_url. It never contains secrets or a review challenge.
These use GET /users/me/account-approvals/{id} and DELETE /users/me/account-approvals/{id}. Reads and cancellation require the same creator; MCP calls also require the same originating credential and mode. Cancellation only affects a pending request. It cannot revoke issued credentials or undo completion. The completed receipt contains keys:[{key_id,type,livemode}], revoked_count, and nullable membership, invitation, managed_identity, and managed_session. Membership receipts identify the action, member, current and previous owner, resulting role, and whether a member was added. They have keys: [] and revoked_count: 0. Credential receipts have membership: null and invitation: null. Invitation receipts have no keys or membership result. Every GET remains metadata-only, even after a lost execution response. No endpoint retrieves a previously delivered secret.

Human browser confirmation

The person opens review_url in the authenticated application and verifies its configured environment, team, action, requested modes and consequences. The link is not a bearer grant and contains no secret. Production uses https://app.gigstack.pro; staging uses its separately configured application origin. The application privately obtains a short-lived, intent-bound review challenge and submits the person’s explicit confirmation. Those browser review and execution actions are excluded from the public API reference and agent tools. They require recent real Firebase sign-in, revocation checking, the same person, and enrolled MFA when applicable; refreshing an old ID token is not recent authentication. Custom/anonymous sessions, managed-user sessions and personal MCP/API credentials cannot perform them. The server rechecks current membership, authority, origin-credential validity, relevant key/account state and applicable entitlement before committing. API rotation revokes only the reviewed key set; a state change invalidates review. MCP creation rechecks the ten-token limit and the person’s explicit terms acceptance. The disclosure version is the application’s review contract, not an independently verified legal PDF revision. Only the first browser execution that commits returns new secrets to that browser. Execution replay returns secrets:null; reads, cancellation and preparation never return secrets or challenges. If that response was lost, inspect the metadata receipt and use a separately reviewed replacement if needed. Do not automatically repeat issuance.

Migrating direct issuance and privileged membership changes

Direct POST /api-keys, POST /api-keys/rotate and POST /users/me/mcp-tokens return HTTP 403 account_approval_required. They no longer return HTTP 201 or credentials. CLI api-keys create, api-keys rotate and me mcp-tokens create now prepare approvals with required --operation-id. Their former --out and --accept-terms issuance options are removed. MCP uses prepare_account_api_keys, prepare_account_api_key_rotation and prepare_my_mcp_token, followed by get_account_approval or cancel_account_approval. List and revoke commands remain available under their existing authority checks. Direct POST /teams/{id}/transfer-ownership now returns 403 account_approval_required. The same error applies to role: admin on member PATCH and add-member POST. Prepare the corresponding action above; preparation itself does not change access. Non-admin role changes, permitted module permissions, and member removal keep their existing authority and direct routes. A completed transfer receipt remains readable by its creator even after they become the previous owner, so a lost response does not require repeating the transfer.

Invite an administrator

Prepare an invitation with an explicit delivery choice:
Send this to POST /users/me/account-approvals, then open review_url. Only the current canonical team owner can approve. For an administrator across the billing account, use billing_account.invitations.create_admin, replace team_id with billing_account_id, and have that account’s canonical owner review. Team ownership, billing administrator status and master-admin flags do not substitute for billing ownership. canonical_owner_required means support must resolve missing ownership. The browser shows the frozen email address, scope, administrator role, invitation expiry and delivery choice in invitation_change. The email address identifies the intended recipient; it is not proof of an existing person’s identity. team is null for billing-account invitations. Access applies across live and test. Preparation expires after ten minutes. A new invitation’s seven-day expiry starts at preparation and is frozen during review. Completion atomically records the approved invitation and receipt.invitation, which contains safe identity/scope metadata. It does not mean an email was delivered or the recipient joined. Only the first committing browser execution may attempt the reviewed email delivery. Replaying execution never sends another email. Use these owner-scoped endpoints for the receipt’s invitation ID: delivery.status=sent records provider acceptance, not recipient acceptance. pending can represent a delivery in progress; an active five-minute lease rejects resend with delivery_in_progress. An expired lease or uncertain provider result requires {"acknowledge_unconfirmed_delivery":true} and can cause a duplicate email. Read the status and obtain that explicit choice before resending. Resend is not an idempotent request: repeating a completed resend can send again. Revocation does not retract an already-sent email. Management responses never expose invitation tokens. To approve an existing unexpired pending admin invitation, include existing_invitation_id in the preparation payload and set send_email:false. Recovery preserves its existing link and expiry. Unknown historical delivery remains unknown. An already-approved or expired invitation cannot be adopted again; revoke and prepare a new invitation when needed. approval_required on management metadata reports missing proof, but acceptance and resend always validate the full proof and current owner authority independently. Direct admin invitation creation returns account_approval_required. Ordinary editor/viewer invitations retain their direct workflow. Administrator acceptance requires the intended recipient’s active Auth account, verified matching email, and current valid owner approval. An existing team member is not silently promoted by accepting a team invitation; use the separate promotion approval. A billing-account invitation explicitly grants account administrator authority, including to someone already associated with that account through an ordinary team seat.

Managed session actions

Prepare delegated access to an existing managed identity using a saved operation ID:
Open the returned review_url for the initiating person. Team API/OAuth keys cannot prepare the action, and agents cannot review, execute, receive or redeem its credential. To request refresh-token revocation instead, use managed_users.revoke_sessions with the same payload shape and a new saved operation ID. It is a separate reviewed action, not cancellation of a prepared request. Both actions require the current canonical billing-account owner and the owner of every reachable team to be the initiating person. The selected team must be within the target’s authoritative access. Private managed provenance must match the current Auth identity; historical from: api or managedBy labels alone are insufficient. Foreign or ambiguous grants are refused. Issuance requires an active target; reviewed revocation can apply to a disabled managed identity. managed_session_change freezes the target ID, email, Auth creation time, billing account, reachable teams/accounts and prior issuance/revocation attempts. Team roles include inherited billing_account_admin and master_team_billing_access where applicable. These disclose current access, not a lifetime restriction on the global Firebase identity. effect_scope is managed_session, and requested_modes: [] means the access is not isolated to test mode. managed_session_execution reports attempting, issued, revoked or unknown, with the attempt timestamp, nullable custom_token_expires_at, and delivery status. For issuance, delivery: not_observable means the backend cannot establish whether the person received or used the credential. A safe completed receipt.managed_session contains the target, approval ID, action and exchange deadline; it never contains a credential. Session fields and this receipt variant are null for other actions. The custom-token deadline limits exchange, not the life of a redeemed Firebase session. A completed issuance does not prove sign-in. After an uncertain or lost response, read this approval; do not replay its effect, automatically start another intent, or treat elapsed token time as permission to issue again. Any new issuance requires a separate human review acknowledging the exact frozen prior attempts. Reviewed revocation invalidates refresh tokens. Already-issued ID tokens can remain usable where consumers do not check revocation, and an outstanding custom token can still be exchanged. A successful revocation does not resolve an earlier unknown issuance. The receipt therefore says revocation_scope: refresh_tokens_only and session_expiration: not_bounded_by_custom_token rather than promising an ended session. The browser handles any first credential privately and deliberately, preserving the owner’s existing session. Public preparation, GET and cancellation always return safe metadata. There is no agent endpoint for recovering a lost credential. Direct POST /users/login-link returns 403 account_approval_required. The legacy Proserver loginUrl and redeem terminals are also retired; old opaque links cannot be redeemed there. Prepare the reviewed action above instead. Session preparation is disabled by default and unavailable in production until an authoritative reverse-grant index with coordinated writers is implemented. It returns 503 managed_session_scope_unavailable before preparation reads when the strategy is unavailable. Do not retry with new operation IDs to bypass this guard. The staging prototype requires explicit GCLOUD_PROJECT=gigstackprodev and MANAGED_SESSION_SCOPE_STRATEGY=prototype_scan. It permits at most 1000 teams, 1000 billing accounts and 100 previous attempts, reading one extra result to detect overflow. 503 managed_session_scope_limit refuses incomplete scope before issuance; a truncated result is never treated as authorized scope. This interim guard preserves the intended reviewed workflow but does not complete production capability. Configuration and rollout must be verified separately; documentation is not evidence that a deployed environment enables the strategy.