Skip to main content
At the end of this page, you will have created an Intelligent Purchase Authorisation (IPA) that returns 202 Accepted with a preflight_workflow_id, polled it through the lifecycle, and approved it — landing the IPA in the approved state, ready for the perpetual search agent to begin executing. The create call: An IPA is the durable contract between a user and an agent. It defines what the user wants, what the agent is allowed to do, for how long, and under what constraints. Once approved, it drives the full perpetual search workflow.
This quickstart uses the post-2026-04-13 IPA model — preflight_workflow_id, originating_chat_id, originating_agent_task_id, and the originating_agent_task / executing_agent_task expansions. The older guides/ipa.mdx reference still describes the legacy workflow_id / workflow_status fields and is being rewritten — treat this quickstart as the source of truth for IPA shapes until that update lands.

Prerequisites

  • A Sumvin-verified user with a deployed Safe. If you don’t have one, run the stand up an account quickstart first.
  • A that grants the scopes this IPA needs. See PINTs for the mint flow and scopes for the full catalog. This quickstart assumes pint_uri = "sr:us:pint:def456" already exists.
  • A Platform API JWT. See authentication.
1

Mint a PINT for the IPA

Perpetual search IPAs need scopes like sr:us:pint:perpetual:search plus any downstream action scopes (for example sr:us:pint:spend:execute if the IPA will authorise purchases).The PINT mint flow is covered in full at PINTs. For this quickstart, assume the PINT URI sr:us:pint:def456 is already signed and stored.
2

Create the IPA

Post the user’s intent, autonomy preferences, and constraints. Include the Idempotency-Key header so retries do not create duplicate IPAs.
curl -X POST https://api.sumvin.com/v0/user/ipa \
  -H "x-juno-jwt: <your-jwt-token>" \
  -H "x-juno-orgid: <your-org-id>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: ipa-req-2026-04-16-0001" \
  -d '{
    "raw_intent": "Find me a pair of Nike Air Max 90 in size 10, under $150",
    "intent_type": "product",
    "autonomy_level": "approve_before_purchase",
    "constraints": { "max_price": 150.00, "currency": "USD" },
    "originating_chat_id": "chat_xyz789",
    "pint_uri": "sr:us:pint:def456"
  }'
Using TanStack Query? useCreateIPA invalidates the IPA list and agent-task queries on success. To forward an Idempotency-Key header, see the mutation patterns page for the recommended wrapper shape.
3

Inspect the 202 Accepted response

Response: 202 Accepted
{
  "intent": {
    "id": "ipa_1a2b3c4d",
    "status": "qualifying",
    "raw_intent": "Find me a pair of Nike Air Max 90 in size 10, under $150",
    "intent_type": "product",
    "autonomy_level": "approve_before_purchase",
    "constraints": { "max_price": 150.00, "currency": "USD" },
    "preflight_workflow_id": "wf_preflight_9a7d2f",
    "originating_chat_id": "chat_xyz789",
    "originating_agent_task_id": null,
    "pint_uri": "sr:us:pint:def456",
    "created_at": 1740000000000
  },
  "_links": {
    "self": { "href": "/v0/user/ipa/ipa_1a2b3c4d" },
    "events": { "href": "/v0/user/ipa/ipa_1a2b3c4d/events" },
    "answers": { "href": "/v0/user/ipa/ipa_1a2b3c4d/answers", "method": "PUT" },
    "decision": { "href": "/v0/user/ipa/ipa_1a2b3c4d/decision", "method": "PUT" },
    "cancel": { "href": "/v0/user/ipa/ipa_1a2b3c4d", "method": "DELETE" }
  }
}
The preflight_workflow_id points to the Upstash durable workflow run that validates the intent and checks the PINT scopes. The IPA status starts as qualifying while preflight runs.
4

Poll the IPA status

Fetch the IPA until it transitions out of qualifying. Use the originating_agent_task expansion to see the preflight agent task in the same response.
curl "https://api.sumvin.com/v0/user/ipa/ipa_1a2b3c4d?expand=originating_agent_task" \
  -H "x-juno-jwt: <your-jwt-token>" \
  -H "x-juno-orgid: <your-org-id>"
Response: 200 OK
{
  "intent": {
    "id": "ipa_1a2b3c4d",
    "status": "pending_approval",
    "preflight_workflow_id": "wf_preflight_9a7d2f",
    "originating_agent_task_id": "task_agent_b7c8d9",
    "originating_agent_task": {
      "id": "task_agent_b7c8d9",
      "status": "completed",
      "agent_type": "preflight"
    }
  }
}
The full set of IPA statuses:
  • qualifying — preflight is validating the intent and scopes
  • searching — the agent is actively crawling for candidates
  • validating — candidates are being scored against constraints
  • pending_clarification — the agent needs more information from the user
  • pending_approval — approved candidate(s) awaiting user sign-off
  • approved — the user approved; the executing agent may proceed
  • monitoring — watching for trigger conditions (price, availability)
  • executing — the purchase is being executed
  • completed — the IPA fulfilled its intent
  • failed — terminal failure
  • expired — lifetime elapsed without fulfilment
  • cancelled — the user cancelled
5

Respond to clarifications (if needed)

If the agent lands in pending_clarification, answer the outstanding questions. The IPA returns to qualifying while the agent incorporates the answers.PUT /v0/user/ipa/{ipa_id}/answers — Submit clarification answers.
curl -X PUT https://api.sumvin.com/v0/user/ipa/ipa_1a2b3c4d/answers \
  -H "x-juno-jwt: <your-jwt-token>" \
  -H "x-juno-orgid: <your-org-id>" \
  -H "Content-Type: application/json" \
  -d '{
    "answers": {
      "preferred_color": "white",
      "new_or_used": "new only"
    }
  }'
Response: 200 OK with intent.status: "qualifying".
6

Approve the IPA

This is the working artefact. Once the IPA is pending_approval, approve it — the executing agent can now begin searching under the terms you set.
curl -X PUT https://api.sumvin.com/v0/user/ipa/ipa_1a2b3c4d/decision \
  -H "x-juno-jwt: <your-jwt-token>" \
  -H "x-juno-orgid: <your-org-id>" \
  -H "Content-Type: application/json" \
  -d '{ "decision": "approved" }'
Using TanStack Query? See invalidation strategy for the multi-level cache invalidation (ipas.all + ipas.detail(id)) this mutation triggers on success.
Response: 200 OK
{
  "intent": {
    "id": "ipa_1a2b3c4d",
    "status": "approved",
    "executing_agent_task_id": "task_agent_exec_3f4e5d"
  },
  "_links": {
    "self": { "href": "/v0/user/ipa/ipa_1a2b3c4d" },
    "cancel": { "href": "/v0/user/ipa/ipa_1a2b3c4d", "method": "DELETE" }
  }
}
The IPA is live. The executing agent has begun work under the scopes, constraints, and autonomy level you defined — and the user can revoke at any time.
7

Cancel at any time

Users can cancel an IPA at any non-terminal state. The executing agent halts and the IPA transitions to cancelled.DELETE /v0/user/ipa/{ipa_id} — Cancel an IPA.
curl -X DELETE https://api.sumvin.com/v0/user/ipa/ipa_1a2b3c4d \
  -H "x-juno-jwt: <your-jwt-token>" \
  -H "x-juno-orgid: <your-org-id>"
Response: 200 OK with intent.status: "cancelled".

What’s next

NextWhereWhen
IPA referenceIPA guideFull field-by-field reference for constraints and autonomy levels
State machineIPA lifecycleWhen debugging a stuck status or wiring approval UI
ScopesScopesPicking which SRI capability strings the IPA carries
PINT mintPINTsBefore the IPA — the primitive IPAs ride on