---
title: "Refusals and cures"
url: https://services.dev/docs/people/refusals
captured: [ask-the-client.txt, legal-refused.txt, legal-region.txt, members-add.txt, sdk.txt]
codes: [act_refused, brand_unverified, input_invalid, needs_a_person, needs_direction, needs_the_party, region_not_ratified, reserved]
---
# Refusals and cures

URL: https://services.dev/docs/people/refusals

> When the rules say no, the answer names the act, the row it cites and the way to yes, and nothing is charged. The same refusal reaches a buyer, an agent and a person.

A refusal answers one question: what does the caller do instead? Every refusal the rules bring names the act, cites the row and its version, and carries a cure, in `next`: the route where the act is performed, the waitlist for a region, or the person to hand a link to. A refusal never charges.

## An act the rules refuse

The legal example refuses litigation in a `shared` row, with a route. Ordering it answers the same way on every surface:

**CLI**

```bash
npx services.dev litigate
```

```txt title="magic values: none"
litigate is never performed here: Litigation is retained directly, never ordered here.
  cites   rules 2026-10 · shared.litigate
  next    hand https://referrals.example.test/litigation to the person it asks
  docs    https://api.lawyer/docs/errors/act_refused
```

**API**

```txt
→ POST /matters {"service":"litigate","max_usd":500,"key":"sue-initech"}
```

```json title="403 · magic values: none"
{
  "type": "BLOCKED",
  "category": "blocked",
  "code": "act_refused",
  "reason": "litigate is never performed here: Litigation is retained directly, never ordered here.",
  "param": "service",
  "act": "litigate",
  "rule": {
    "version": "2026-10",
    "at": "shared.litigate",
    "position": "Litigation is retained directly, never ordered here."
  },
  "cure": {
    "route": "https://referrals.example.test/litigation"
  },
  "next": {
    "do": "hand_to_person",
    "url": "https://referrals.example.test/litigation",
    "arguments": {},
    "tool": null,
    "http": "GET https://referrals.example.test/litigation"
  },
  "doc_url": "https://api.lawyer/docs/errors/act_refused",
  "request_id": "req_cXmV9f",
  "simulated": true
}

← GET /owner/events: no matter.ordered and no charge: $0
```

**MCP**

```txt
→ tools/call order_litigate {"max_usd":500}
```

```txt title="magic values: none"
← isError: true
  act_refused: litigate is never performed here: Litigation is retained directly, never ordered here.
    next  hand https://referrals.example.test/litigation to the person it asks
    docs  https://api.lawyer/docs/errors/act_refused
```

**SDK**

The SDK calls the API and throws its answer as a `BlockedError`, with the same code and `next`. Its types name every code an order can answer:

```bash
npx services.dev sdk
```

```txt title="magic values: none"
  "service.order": "input_invalid" | "policy_invalid" | "key_reused" | "not_found" | "not_live" | "act_refused" | "region_not_ratified" | "brand_unverified" | "period_taken" | "key_missing" | "key_invalid" | "body_invalid" | "version_unknown" | "api_error"
    /** Order a job, or get the offer: the price and the exact next call. A Service whose price has every answers a subscription, sbn_…. `POST /jobs` with service: "translation"; refused with ServicesError<'service.order'>. */
```

Nothing was ordered and nothing was charged: the brand's feed has no `matter.ordered` (the legal brand's word for `job.ordered`), and the ledger reads $0.

## Each refusal, and its cure

| Code | Who hears it | It carries | The cure in `next` |
|---|---|---|---|
| [`act_refused`](https://services.dev/docs/reference/errors.md#act_refused) | the buyer or their agent, at the order | the act, the row and its position, `cure.route` | `hand_to_person`, with the route |
| [`region_not_ratified`](https://services.dev/docs/reference/errors.md#region_not_ratified) | the buyer, at the order | the act, the order's region, the ratified `regions`, the row | `waitlist` |
| [`brand_unverified`](https://services.dev/docs/reference/errors.md#brand_unverified) | the buyer, at the order | the act, the brand credentials it needs, the row | `waitlist` |
| [`reserved`](https://services.dev/docs/reference/errors.md#reserved) | a person who attests without the credential | the act, who it is reserved to, the row | a person who holds it attests |
| [`needs_a_person`](https://services.dev/docs/reference/errors.md#needs_a_person) | a key or a tool that tries a person's act | the act | `hand_to_person`, with the person's app |
| [`needs_the_party`](https://services.dev/docs/reference/errors.md#needs_the_party) | anyone but the party an ask waits on | the ask and the party | `hand_to_person`, with the party's link |
| [`needs_direction`](https://services.dev/docs/reference/errors.md#needs_direction) | anyone but the client, after a decline | the step | the client's direct ask |

The order-time refusals run before anything is held, one step at a time, in the order the Service writes its steps: a refused act first, then a reserved act whose region the order doesn't name, which answers [`input_invalid`](https://services.dev/docs/reference/errors.md#input_invalid) with the input to send, then a region outside the row's `regions`, then a stale brand credential. A step the client performs themselves, under `posture: 'self'`, is their own act, so its row's regions and credentials don't bind it. A region outside the row's `regions` hears the waitlist, and joining it is one call:

```txt
→ POST /contract-review/waitlist {"email":"ada@example.com"}   # the next the refusal named
```

```txt title="magic values: none"
← 200 {"object":"waitlist","service":"contract-review","status":"live","position":1,"simulated":true}
```

## Only a person, and only the party

A person's act is theirs, and no key or tool can take it. The member CLI without the member's own session answers:

```bash
npx services.dev reviews list
```

```txt title="magic values: none"
Only a signer, in their own session at http://localhost:8787/attorneys, does this. A key never can.
  next    hand http://localhost:8787/attorneys to the person it asks
  docs    https://api.lawyer/docs/errors/needs_a_person
```

An ask waits on its party, and a member who tries to attest past it hears who to hand the link to:

```txt
→ POST /reviews/tsk_7Hq2/attest   # as mbr_7Hq2, before the reply
```

```txt title="magic values: none"
← 403 needs_the_party: advise waits on Ada Lovelace to answer. Only they can, through their own link. Hand them the link in next.
```

These refusals are the boundary working. AI delivers by default, people come in where you want or need them, and every caller hears exactly who acts next.

## Why a refusal charges nothing

A refusal is the Service keeping to its rules, so it costs the buyer nothing, and the brand keeps nothing. An order refused at the door holds no money. A person's act refused at the gate leaves their Task open, so they can perform it again with the credential or the input it needs. A decline is different: it is a person's act, paid, and [Declines and direction](https://services.dev/docs/people/direction.md) has it.

## Refusals from check

`check` catches the rest before a Service takes an order: [`act_unruled`](https://services.dev/docs/reference/check/act_unruled.md), [`reserved_act_unstaffed`](https://services.dev/docs/reference/check/reserved_act_unstaffed.md), [`rail_conflict`](https://services.dev/docs/reference/check/rail_conflict.md) and [`brand_credential_missing`](https://services.dev/docs/reference/check/brand_credential_missing.md). [check's gates](https://services.dev/docs/reference/check.md) lists every one.

---

- Up: [human: the line](https://services.dev/docs/people.md)
- Previous: [Where an act happens](https://services.dev/docs/people/where.md)
- Next: [When the client does it themselves](https://services.dev/docs/people/self.md)
