> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sumvin.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Errands

> Create, inspect, and drive an Errand through its lifecycle using the Platform API.

<Snippet file="product-term-disambiguation.mdx" />

An <Tooltip headline="Errand" tip="An agent's scope-bound tasking run: Intent → Authorization → Vigilance." cta="Glossary →" href="/glossary">Errand</Tooltip> is the durable contract between a user and an agent — what the user wants, what the agent may do, and under which signed authorisations. This guide covers the Platform API surface: request and response shape, lifecycle actions, and how to expand related resources. On the wire, an Errand is created and driven through the `IPA` (Intelligent Purchase Authorisation) routes and lifecycle. For the concept and composition model, see [Errands](/concepts/errands); for the state machine, see [Errand lifecycle](/products/errand/errand-lifecycle).

<Info>
  An Errand sits **above** its mandates. The Errand handles orchestration (finding, validating, approving); a <Tooltip headline="Stamped Mandate" tip="A signed authorisation a user grants for specific scoped actions — delivered on the wire as a PINT." cta="Glossary →" href="/glossary">Stamped Mandate (PINT)</Tooltip> with `sr:us:pint:spend:execute` authorises the on-chain transaction at execution time. See [scopes](/identity/scopes).
</Info>

## Prerequisites

* A verified user with a deployed Safe — see [onboarding](/guides/onboarding).
* A signed Stamped Mandate that carries the scopes the Errand needs (at minimum `sr:us:pint:perpetual:search`; add `sr:us:pint:spend:execute` to authorise execution). See [Stamped Mandates](/identity/pint) for the mint flow and [scopes](/identity/scopes) for the catalog.
* A Platform API JWT — see [authentication](/authentication).

## Create an Errand

On the wire, you create an Errand with `POST /v0/user/ipa`, which returns `202 Accepted` once the pre-flight workflow is triggered. Pass `Idempotency-Key` to guard against duplicate submissions: if a previous request with the same key successfully produced an Errand, the retry returns that original Errand with `208 Already Reported`. If the previous attempt did not produce an Errand (e.g. it failed before creation), the retry is processed as a new request.

```bash theme={null}
curl -X POST https://api.sumvin.com/v0/user/ipa \
  -H "x-juno-jwt: <token>" \
  -H "x-juno-orgid: <your-org-id>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: ipa-req-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"
  }'
```

### Request fields

| Field                       | Type   | Required | Description                                                                                                |
| --------------------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------- |
| `raw_intent`                | string | Yes      | The user's request in natural language (1–2000 chars). Preserved verbatim for audit and re-parsing.        |
| `intent_type`               | enum   | No       | `product`, `service`, or `composite`. Default: `product`.                                                  |
| `autonomy_level`            | enum   | No       | `supervised`, `approve_before_purchase` (default), `auto_within_conditions`, `autonomous`.                 |
| `constraints`               | object | No       | Selection filters (what results are acceptable). See [constraints](#constraints).                          |
| `conditions`                | array  | No       | Auto-execution triggers. Only evaluated when `autonomy_level = auto_within_conditions`.                    |
| `originating_chat_id`       | string | No       | External ID of the chat session this Errand came from — carried through for traceability.                  |
| `originating_agent_task_id` | string | No       | External ID of an existing agent task to attach this Errand to. Mutually exclusive with `Idempotency-Key`. |

<Tip>
  `constraints` answer **what** is acceptable (e.g. `max_price = 200`). `conditions` answer **when** an approved Errand may auto-execute (e.g. buy if price drops below 180). They are evaluated at different stages — don't conflate them.
</Tip>

### Response shape

```json theme={null}
{
  "intent": {
    "id": "ipa_1a2b3c4d",
    "intent_type": "product",
    "status": "qualifying",
    "autonomy_level": "approve_before_purchase",
    "raw_intent": "Find me a pair of Nike Air Max 90 in size 10, under $150",
    "constraints": { "max_price": 150.00, "currency": "USD" },
    "preflight_workflow_id": "wf_preflight_9a7d2f",
    "pint_uris": null,
    "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" },
    "cancel": { "href": "/v0/user/ipa/ipa_1a2b3c4d", "method": "DELETE" }
  }
}
```

### Key response fields

| Field                   | Description                                                                                                                                                                                                                                                                                                                                                                 |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                    | The Errand's external ID. Use as `{ipa_id}` in subsequent requests.                                                                                                                                                                                                                                                                                                         |
| `status`                | Current lifecycle state. See [Errand lifecycle](/products/errand/errand-lifecycle) for the full state machine.                                                                                                                                                                                                                                                              |
| `preflight_workflow_id` | A workflow identifier for the preflight that parses and qualifies the intent.                                                                                                                                                                                                                                                                                               |
| `pint_uris`             | Stamped Mandates explicitly linked to the originating and, once present, executing agent tasks. Near-always `null`: creating an Errand links nothing, and the mandate an Errand actually spends under is reserved later in its lifecycle. A URI appears here only after an explicit link via `POST /v0/user/strategies/{user_strategy_id}/tasks/{task_external_id}/pints/`. |
| `constraints`           | Echoed and parsed from the request.                                                                                                                                                                                                                                                                                                                                         |
| `conditions`            | Parsed auto-execution triggers (when supplied).                                                                                                                                                                                                                                                                                                                             |
| `_links`                | <Tooltip headline="HAL" tip="Hypertext Application Language — the link format used on every Sumvin response." cta="Glossary →" href="/glossary">HAL</Tooltip> links indicating which actions are valid for the current state.                                                                                                                                               |

<Note>
  The originating and executing agent tasks, candidates, manifests, and events are not returned by default — fetch them via [`expand`](#expansions).
</Note>

## Drive the lifecycle

The `_links` field on every Errand response tells you which actions are currently valid. For the full state diagram, see [Errand lifecycle](/products/errand/errand-lifecycle).

### Submit clarification answers

When the Errand is in `qualifying` or `pending_clarification`, the `answers` link is present and `clarification_questions` is populated.

```bash theme={null}
curl -X PUT https://api.sumvin.com/v0/user/ipa/ipa_1a2b3c4d/answers \
  -H "x-juno-jwt: <token>" \
  -H "x-juno-orgid: <your-org-id>" \
  -H "Content-Type: application/json" \
  -d '{ "answers": { "preferred_color": "white", "new_or_used": "new only" } }'
```

Returns `200 OK` with `status: "qualifying"` — the agent re-parses with the new context.

### Approve or reject

In `pending_approval`, submit a decision. Approving authorises spending, so it is signed by the account holder. Rejecting authorises nothing, and needs no signature.

Start by fetching the payload prepared for this Errand:

```bash theme={null}
curl "https://api.sumvin.com/v0/user/ipa/ipa_1a2b3c4d?expand=mandate" \
  -H "x-juno-jwt: <token>" \
  -H "x-juno-orgid: <your-org-id>"
```

`intent.approval_payload` is an EIP-712 typed-data document describing the spend ceiling, the conditions and the deadline being authorised. Sign it with the wallet on the account — `eth_signTypedData_v4` — and send the signature back:

```bash theme={null}
curl -X PUT https://api.sumvin.com/v0/user/ipa/ipa_1a2b3c4d/decision \
  -H "x-juno-jwt: <token>" \
  -H "x-juno-orgid: <your-org-id>" \
  -H "Content-Type: application/json" \
  -d '{ "decision": "approved", "signature": "0x<65-byte-signature>" }'
```

What the purchase is bounded by is read from the signed payload, never from this request, so an approval always means exactly what was signed. To change those bounds, replace the conditions first with `PUT /v0/user/ipa/{ipa_id}/conditions` — it returns a rewritten payload that supersedes any copy fetched earlier, and it is refused once the approval has been signed.

An approval sent without a signature is rejected with `401` and error code `IPA-401-001`; one signed by anything other than the wallet on the account is rejected too.

Rejecting is terminal and carries no signature:

```bash theme={null}
curl -X PUT https://api.sumvin.com/v0/user/ipa/ipa_1a2b3c4d/decision \
  -H "x-juno-jwt: <token>" \
  -H "x-juno-orgid: <your-org-id>" \
  -H "Content-Type: application/json" \
  -d '{ "decision": "rejected" }'
```

### Cancel

Any non-terminal Errand can be cancelled. The pre-flight or executing workflow is halted and the Errand transitions to `cancelled`.

```bash theme={null}
curl -X DELETE https://api.sumvin.com/v0/user/ipa/ipa_1a2b3c4d \
  -H "x-juno-jwt: <token>" \
  -H "x-juno-orgid: <your-org-id>"
```

Returns `200 OK`, or `409 Conflict` if the Errand is already terminal (`completed`, `failed`, `expired`, `cancelled`).

## Read an Errand

```bash theme={null}
curl https://api.sumvin.com/v0/user/ipa/ipa_1a2b3c4d \
  -H "x-juno-jwt: <token>" \
  -H "x-juno-orgid: <your-org-id>"
```

### Expansions

Add `expand` query parameters to embed related resources in the same response. Without `expand`, these fields are `null`.

| Expansion                | Field populated          | Shape                                                                                                                        |
| ------------------------ | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
| `originating_agent_task` | `originating_agent_task` | Agent task that created the Errand (e.g. the pre-flight task).                                                               |
| `executing_agent_task`   | `executing_agent_task`   | Agent task that carries the Errand into execution. Spawned during pre-flight, so it is available before approval is granted. |
| `candidates`             | `candidates`             | Scored candidate results produced during `searching` and `validating`.                                                       |
| `manifests`              | `manifests`              | Purchase manifests constructed once a candidate is selected.                                                                 |
| `events`                 | `events`                 | Lifecycle event stream (same content as `GET /v0/user/ipa/{ipa_id}/events`).                                                 |
| `mandate`                | `approval_payload`       | The EIP-712 payload to sign to approve this Errand's purchase, when one is awaiting signature.                               |
| `capacity`               | `capacity`               | Remaining spend allowance of the mandate authorising the Errand.                                                             |
| `manifest_summary`       | `manifest_summary`       | Headline totals of the Errand's purchase manifest.                                                                           |

```bash theme={null}
curl "https://api.sumvin.com/v0/user/ipa/ipa_1a2b3c4d?expand=originating_agent_task&expand=executing_agent_task" \
  -H "x-juno-jwt: <token>" \
  -H "x-juno-orgid: <your-org-id>"
```

### List Errands

```bash theme={null}
curl "https://api.sumvin.com/v0/user/ipa?status=pending_approval&sort=-created_at&limit=20" \
  -H "x-juno-jwt: <token>" \
  -H "x-juno-orgid: <your-org-id>"
```

| Parameter     | Description                                                          |
| ------------- | -------------------------------------------------------------------- |
| `status`      | Filter by Errand status.                                             |
| `intent_type` | `product`, `service`, `composite`.                                   |
| `sort`        | `created_at`, `updated_at`, or `status`. Prefix `-` for descending.  |
| `offset`      | Page offset, `≥0`. Default `0`.                                      |
| `limit`       | Page size, `1–100`. Default `20`.                                    |
| `expand`      | Repeat per resource to expand — same options as the detail endpoint. |

The response includes HAL `next`/`prev` links when more pages exist.

### Event stream

`GET /v0/user/ipa/{ipa_id}/events` returns every state change, clarification exchange, approval decision, workflow transition, and cancellation recorded against the Errand. Fetch it directly, or embed it via `expand=events` on the detail endpoint.

## Constraints

Structured requirements that define what results the agent may propose. Evaluated during parsing, search, validation, and manifest construction — not during execution monitoring.

| Field               | Type    | Description                       |
| ------------------- | ------- | --------------------------------- |
| `max_price`         | number  | Maximum price per item.           |
| `max_total`         | number  | Maximum total spend.              |
| `currency`          | string  | Currency code (e.g. `USD`).       |
| `deadline`          | integer | Deadline timestamp (epoch ms).    |
| `preferred_sellers` | array   | Preferred seller identifiers.     |
| `excluded_sellers`  | array   | Sellers to exclude.               |
| `extra`             | object  | Additional key-value constraints. |

## Conditions

Auto-execution triggers evaluated once an Errand is approved with `autonomy_level = auto_within_conditions`. Each condition is typed by `type` (`price_target`, `budget_cap`, `availability`, `time_window`, `flight_route`, `coverage_minimum`, `jurisdiction`, `group`). See the [Create Errand](/api-reference/ipa/create-ipa) reference for the per-type schemas.

## Idempotency and HAL

* `Idempotency-Key` on `POST /v0/user/ipa` deduplicates retries **when a prior request with the same key already produced an Errand** — that original is returned with `208 Already Reported`. Retries of a failed prior attempt are processed as new requests. Mutually exclusive with `originating_agent_task_id` in the body.
* Every response carries `_links` — the presence of a link is the authoritative signal that the action is valid. See [HAL, RFC 7807, idempotency, pagination](/concepts/hal-rfc7807-idempotency-pagination).

## Errors

All errors follow [RFC 7807 Problem Details](/error-handling) with stable `error_code` values (e.g. `IPA-404-001`, `IPA-409-001`).

| Status                   | Meaning                                                             |
| ------------------------ | ------------------------------------------------------------------- |
| 401 Unauthorized         | Missing or invalid JWT.                                             |
| 404 Not Found            | Errand does not exist or does not belong to the authenticated user. |
| 409 Conflict             | Errand is terminal and cannot be modified or cancelled.             |
| 422 Unprocessable Entity | Request body failed validation.                                     |

## Related

* [Errands](/concepts/errands) — the concept page (what an Errand is, how it composes with Stamped Mandates).
* [Errand lifecycle](/products/errand/errand-lifecycle) — full state machine and transition reference.
* [Stamped Mandates](/identity/pint) — the signed primitive the Errand draws against.
* [Scopes](/identity/scopes) — capability strings an Errand's Stamped Mandates must carry.
* [Set up an Errand](/guides/quickstarts/set-up-errand) — working end-to-end quickstart.
* [Errand API reference](/api-reference/ipa/create-ipa) — full OpenAPI detail.
