Skip to main content

OTP approvals

OTP approvals is the second-supervisor gate for the two highest-leverage pieces of Orbit Verify:
  • an OTP message template going live, and
  • a resend burst on an existing verification (a flurry of resend requests against one verification).
When the gate is on, anyone who submits a matching change becomes the requester. Nothing leaves the queue until a different owner or admin approves it — the requester may not approve their own request. A self-approve attempt is rejected with 409 Conflict. This is the same four-eyes pattern used for campaign launches, so the queue reads identically across gated surfaces.

Turn the policy on or off

The policy has three fields: Update the policy from the dashboard (any owner/admin), or read and write it over the API:
A valid PUT body is the row with your changes:

Work the queue

Every pending item shows the requester (the teammate’s user id), the kind (otp_template or resend_burst), the rendered template body or the burst metadata it would release, and when it was queued. Work the queue from the dashboard under Outbound → OTP approvals, or over the API:
  • Approve releases the request. A gated template goes live; a gated resend burst re-enters the ordinary Verify dispatch chain and delivers through the normal channel router — approval decides nothing more than the policy gate, it never touches the delivery path itself.
  • Reject holds the request back. The body may carry an optional reason so the requester sees why; with no reason the requester just sees the rejection.
  • Self-approve is a hard no. If the approver is the same user as the requester, the API returns 409 Conflict. It is the single most-asked-about constraint — the whole point of a four-eyes gate is that the person who submits is not the person who signs.
Only owner and admin roles may read the pending queue, approve, reject, or write the settings; everyone else gets 403.

Read a pending item

A queued resend burst looks like this:
For otp_template rows, rendered_body carries the exact template copy the approver judges; for resend_burst rows it stays null and the approver decides against the burst_count / window_seconds pair. When the gate is off, the pending endpoint returns an empty list and nothing accrues.

Troubleshooting

  • “I approved my own request and it came back with 409.” Working as designed — the approver must not be the requester. Have a second owner or admin decide the item, or reject it yourself to clear the queue.
  • “The pending queue is empty even though I just submitted a template.” The gate is off (require_approval_default is false), or the burst fell below resend_burst_threshold when a threshold is set. Also check your role: the queue is supervisor-only and other roles get 403.
  • “Approving a burst doesn’t resend immediately.” Approval only releases the gate. The resend is handed back to the normal Verify dispatch and still respects the verification’s expiry, channel fallback, and rate limits — nothing is sent from a parallel path.
Still stuck? See the Verify overview and the Troubleshooting index.