> ## 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.

# Read a mandate's scopes

> Turn the scopes on a Stamped Mandate into ceilings you can compare against a request, with readScopeCeiling.

export const waitlists = {
  earlyAccess: "https://sumvin.com/?interest=early_access&utm_source=docs&utm_medium=banner&utm_campaign=early_access#waitlist",
  payments: "https://sumvin.com/?interest=payments&utm_source=docs&utm_medium=banner&utm_campaign=payments#waitlist",
  openBanking: "https://sumvin.com/?interest=open_banking&utm_source=docs&utm_medium=banner&utm_campaign=open_banking#waitlist",
  developers: "https://sumvin.com/developers?interest=cli,agent_plugin&utm_source=docs&utm_medium=banner&utm_campaign=developers#access",
  verifiers: "https://sumvin.com/developers?interest=verifiers&utm_source=docs&utm_medium=banner&utm_campaign=verifiers#access"
};

<Note>
  **Private preview:** this is rolling out and may not be available on your account yet.{waitlists.earlyAccess ? <> <a href={waitlists.earlyAccess}>Request early access →</a></> : null}
</Note>

A Stamped Mandate permits only what its [scopes](/concepts/mandates/scopes) say. Before you act, check that the request in front of you is inside them. The scope language, parameters and limits are described in [The mandate language](/concepts/mandates/language) and [Limits and narrowing](/concepts/mandates/limits); this page covers reading them in code.

## Read a spending ceiling

`readScopeCeiling` reads the ceiling one scope states. It works offline on the scope string alone, so you can use it on the `scopes` from the [exchange](/sdk/verify/checks#exchange).

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import { isScopeCeilingError, readScopeCeiling } from "@sumvin/sdk";

readScopeCeiling("sr:us:pint:spend:visa_checkout?max=25&currency=USD");
// { kind: "fiat", amount: "25.00", currency: "USD", decimals: 2 }

readScopeCeiling("sr:us:pint:sigil:proof_of_personhood");
// null: this scope states no ceiling
```

`max` is always in the display unit of the currency: `max=25&currency=USD` is 25.00 US dollars, never 25 cents. `amount` comes back as an exact decimal string, padded to the currency's precision. Compare it as a decimal, never as a floating-point number.

<Note>
  Spending scopes belong to payments, which arrive in a fast-follow release. Identity scopes such as `sr:us:pint:sigil:proof_of_personhood` state no ceiling.
</Note>

## Read every scope

The reader handles one scope at a time. Read every scope on the mandate, not only the first.

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
const ceilings = scopes
  .map((scope) => ({ scope, ceiling: readScopeCeiling(scope) }))
  .filter(({ ceiling }) => ceiling !== null);
```

## When it refuses

The reader refuses rather than guesses. It throws a `ScopeCeilingError` whose `reason` is one of:

| Reason | Means |
| - | - |
| `malformed-scope` | The scope, or its parameters, aren't written the way the language allows. |
| `invalid-amount` | `max` isn't a plain positive decimal. |
| `missing-denomination` | `max` names no currency or asset. |
| `ambiguous-denomination` | It names both a currency and an asset. |
| `unknown-denomination` | The currency or asset isn't one the SDK knows. |
| `over-precise` | `max` has more decimal places than the currency allows, such as `25.001` USD. |

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
try {
  readScopeCeiling(scope);
} catch (e) {
  if (isScopeCeilingError(e)) {
    // Unreadable: refuse the request.
  }
}
```

**Treat a refusal as unreadable, never as unlimited.** Refuse the request.

`errand:search` takes an optional `max` but names no currency, and that `max` is not enforced (see [Scopes](/concepts/mandates/scopes)). A `max` written there has no currency to read, so the reader refuses it as `missing-denomination`. The ceiling that counts is on `spend:visa_checkout`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.