Server and agent flows
Use the API directly when there’s no browser for the embed, such as a check from your server or an MCP tool that binds a policy. For a website, use the embed, which handles all of this.
Creating the review from your server is also the most secure setup: the quote goes from your server to HumanApproved, so it never passes through the agent.
Before you start
Set your keys and your region’s address as environment variables. Use test keys while you build.
Every call except /api/v1/server/* needs an Origin header that is one of the product’s allowed websites for the key’s environment. Browsers send it themselves. From a server, send it yourself, for example Origin: https://www.example.com.
Make sure the check asks for approval
From a server there’s no browser to observe, so HumanApproved only sees your server’s own request. Decide on the product instead:
- Every purchase through the flow is an agent’s (for example an MCP tool): set the product’s When to ask for approval to Every purchase and publish. Every check returns
review. - You know which purchases are an agent’s: set the product to use your own signal on its Agent detection page, and send
"signal": { "source": "mcp", "isAgent": true }with the check. It returnsreviewunless the product is set to never ask (monitor only).
The lifecycle
Create a check
Send your quote reference with the publishable key.
The response is continue or review:
On continue, go ahead and report the result. On review, keep the review’s id and token on your server against the quote reference. The token is shown once, and only it can send the quote and read the status.
Send the quote
Send the quote and the customer’s mobile with the review’s token, once, while the review is waiting for it. The quote must match the product’s published fields; fields it doesn’t define are dropped.
Then show the customer, or the agent, the approval link (url). A missing or wrongly typed field returns 422 invalid_quote, with fields listing each one. A second send returns 409 quote_already_set: treat it as sent.
Poll the status
Poll every 3 seconds, then every 10 seconds after 10 minutes. After an error, slow down to at most once every 60 seconds. Stop at approved, declined, expired or the review’s expiresAt. Before you bind, verify the review on your server with your secret key.
Pass the link to an agent, and resume
An agent can’t approve: only the customer can. The agent passes the link to the customer and checks back later. Give it the review’s url with instructions, keep the review’s ID and token on your server against the quote reference, and check the status when the agent calls again.
Never give the agent the review token, or any of your keys. The token is the review’s credential: keep it on your server. Return only the approval link and instructions.
This example bind_policy tool for an agent, for example in an MCP server, runs on your server:
reviews, bind and quoteDetails are your own: a store for the review, your bind, and the quote and mobile for that reference from your own records. Report each check’s result, and treat a 401 or 403 on the status call as expired, as described in The lifecycle.
Use the product’s own words
The check’s review.agentPanel.text holds every piece of wording the embed’s pause panel shows: your product’s wording from its Agent popup page, or the standard wording. Use it so an agent gets the same wording whichever way it buys:
relayasks the agent to send the link to the customer.instructionsholds your own extra instructions, empty when there are none.nevertells the agent not to open or approve the link itself.
The text is plain, with no markup or links. Some pieces contain placeholders, such as {expiry}, {reason} and {brand}, for you to fill in. Whatever you show, make sure the agent knows not to open or approve the link itself. See The pause panel.
Related
- Verify on your server: read the outcome with your secret key before you bind.