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

# Capability Grants

> How a user authorises you to ask Array something about them, what you can ask today, and how the set is agreed per integration.

<Note>
  **Maturity:** Limited preview. Grants ship and work. This page is an explainer
  rather than a full reference, so it covers the model and what is answerable
  today, not every option and error code.
</Note>

A sign-in tells you who is at the door. A **capability grant** is the separate
thing that lets you ask Array a question about them afterwards.

The device mints it during the same consent ceremony that produces the login
token, signed with the same key. It names the capabilities the user approved,
binds to your registered key so no other application can present it, and
expires.

## What the user sees

The consent sheet is the whole trust surface. Your display name and logo come
from the client directory, not from your request, so you cannot choose the
words that describe you. Each capability you asked for appears as one plain
line, written in the second person.

<div style={{display:"flex",justifyContent:"center",margin:"2rem 0"}}>
  <img src="https://mintcdn.com/vibecheck-b5703897/WL2tkzlyQEX6JPL8/images/consent-sheet.svg?fit=max&auto=format&n=WL2tkzlyQEX6JPL8&q=85&s=396d93eca7fd96fba7bbabd50a353602" alt="The Alive consent sheet for a sign-in requesting the connection capability" width="380" data-path="images/consent-sheet.svg" />
</div>

Above: a sign-in from an application called Acme, asking for the `connection`
capability, with a 7-day standing grant selected. Reproduced from the shipped
component's own stylesheet and copy, so the wording and colours match the app
rather than approximating it.

The duration control only appears when a standing grant is on offer, and the
note under it changes with the choice. Picking anything longer than a session
says plainly that the app can check while the user is away.

Two things follow from this that are worth designing around. Approval is
all-or-nothing, so a long capability list is one decision rather than several,
and asking for less makes the sheet easier to say yes to. And the sheet names
you, so a capability that is hard to justify in one line is one your users will
decline.

## Why it is a second artifact

The model this replaces is the familiar one: an application holds an API key
and queries a service about whoever it likes. That gives any integration a
standing ability to ask about people who never agreed to be asked about, and
the only control available is a policy saying don't.

A grant makes it structural instead. **Two things are required for any question
about a person, and neither substitutes for the other.**

Your **M2M key** carries the scopes your integration was granted.
That is the ceiling on what you could ever ask. The **grant** is what this
particular user allowed you to ask underneath that ceiling. A bare machine key
resolves no person, and a grant alone opens no route.

The ceiling is enforced in three places, which is why a misconfigured
integration fails early rather than at the last step. The admin grant sets it,
the device refuses to mint a grant for a capability you are not scoped for
before any consent sheet appears, and the service checks it again on the way
in.

## What you can ask today

| Capability | Question | Disclosed | Pairwise | Standing cap |
| - | - | - | - | - |
| `membership` | Is this an admitted network member? | proved on device | proved on device | n/a |
| `connection` | Are these two connected? | ask array-api | not reachable | 30 days |
| `binding` | Which social handle is bound? | ask array-identity | not reachable | 24 hours |
| `still_connected` | Is this connection still live? | not yet | not yet | n/a |
| `trust` | Is the trust score above a threshold? | not yet | not yet | n/a |

`membership` never involves asking Array anything. The user proves it on their
device and you verify the proof, which is what the quickstart already does.

The last two rows are listed because they exist in the registry and an operator
deciding what your integration may ask will see them. Neither has a circuit or
a route yet, so nothing can answer them.

**Pairwise sign-ins cannot ask anything.** That is not a policy, it is a
consequence: a pairwise subject is a pseudonym no Array service can resolve, so
there is no question to put. If your integration needs to ask, it needs
disclosed mode.

## Session and standing

By default a grant is session-lived. It lasts minutes, answers one ask, and is
burned on use. An operation that makes two reads will get `grant_used` on the
second, which is the burn working rather than a bug.

A user can instead approve a **standing grant** at consent time, up to the
per-capability cap above, which lets you ask again later without them present.
That is the case for a nightly job or a periodic recheck. Standing grants are
listed in the app and the user can revoke one at any time. Revocation works
because a grant is verified by an Array service rather than offline, so a
revocation check costs nothing.

A standing grant widens *when* you may ask, never *what*. The capability list
is fixed when it is minted.

## Agreeing your capability set

<Note>
  We work through the capability set with each relying party rather than handing
  out a default. Which capabilities your integration needs, whether any of them
  should be standing and for how long, and whether disclosed mode is justified at
  all are decisions we would rather make with you than have you discover through
  refusals.
</Note>

Bring the question you are trying to answer. Often the answer is that you need
less than you expected, because `membership` is proved on the device and costs
no grant at all. Starting from the smallest set that works is also the easiest
position to explain to your own users on the consent sheet, which shows them
exactly what they are approving.

## Requesting one

Name the capabilities in the sign-in request, and the device folds them into
the same consent sheet:

```ts theme={null}
const claims = JSON.parse(createSignInRequest({
  clientId: "my-rp",
  nonce,
  responseEndpoint: "https://api.my-rp.com/auth/siop-response",
  scope: "arrayid",                 // grants need disclosed mode
  capabilities: ["connection"],
  standingSeconds: 7 * 24 * 60 * 60, // a request; the device clamps it
}));
```

The grant arrives alongside the login token and is verified on your server with
`verifyGrantToken` from the [RP server SDK](/build/sdks/rp-server), passing
`expectedMode: "disclosed"`. A grant in the other mode is refused as
`grant_invalid`. Asking
array-api then uses `@vibechecklabs/array-protocol-server`, which presents the
grant with a fresh proof that you hold your registered key.

Full reference for both, including every refusal code, lands in a later release
of this guide. Until then, ask us.


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