---
title: "Suggest a least-privilege grant for a key"
method: GET
path: "/keys/{id}/suggestion"
tags: ["Credentials"]
---

# Suggest a least-privilege grant for a key

`GET /keys/{id}/suggestion`

## Request

- Base URL: `https://api.primitive.dev/v1`
- URL: `https://api.primitive.dev/v1/keys/{id}/suggestion`
- Auth: HTTP bearer

The permissions a key used over the last 30 days, as a custom grant that would have served every successful call (also as builder areas), the narrowest mail scope and depth its calls support (the mailboxes of the messages it named and sent, with notes on what the request log cannot account for), and whether it is unused. Calls to routes only the super admin key can use (groups and mailbox access) derive no permission, since a custom key is refused there; super_admin_only_calls counts them. usage gives the same window anonymized: successful and failed requests per UTC day, the routes called by their declared template (never the called path) with the permission each needed, and how many mailboxes the key read and sent from (counts only, and only for a person with access to the whole organization's mail). Nothing is applied: narrowing is a change to the key (PATCH /v1/keys/:id). Needs the organization's credential features to be enabled; while they are not, this answers 404 feature_disabled.

Person only: a dashboard session. The person's role must hold credentials:read. API keys, agent connection keys and agents are refused.

## Path parameters

- `id` string, required

## Response `200`

Success

- object
  - `success` true, required
  - `data` CredentialsGetKeySuggestionResult, required
    - `key_id` string, required
    - `permissions` string[], required
    - `matrix` object, required
    - `calls` number, required
    - `unmatched` number, required
    - `covers_super_admin` boolean, required
    - `unused` boolean, required
    - `warnings` object[], required
      - `permission` string, required
      - `adds` string[], required
      - `why` string, required
      - `description` string, required
    - `super_admin_only_calls` number
    - `areas` object[]
      - `id` string, required
      - `label` string, required
      - `level` 'read' | 'write', required
      - `partial` boolean, required
    - `narrowing` object
      - `available` boolean, required
      - `reason` string, nullable, required
      - `message` string, nullable, required
    - `mail_scope` object, nullable
      - `available` boolean, required
      - `unavailable_message` string, nullable, required
      - `addresses` string[], required
      - `domains` string[], required
      - `depth` 'metadata' | 'content' | 'raw', required
      - `depth_reason` string, required
      - `complete` boolean, required
      - `blocked_by` string[], required
      - `notes` string[], required
    - `usage` object
      - `days` number, required
      - `daily` object[], required
        - `day` string, required
        - `requests` number, required
        - `errors` number, required
      - `total_requests` number, required
      - `error_requests` number, required
      - `active_days` number, required
      - `distinct_routes` number, required
      - `top_route_share` number, nullable, required
      - `routes` object[], required
        - `method` string, required
        - `route` string, nullable, required
        - `requests` number, required
        - `permissions` string[], required
        - `super_admin_only` boolean, required
      - `routes_truncated` boolean, required
      - `history_truncated` boolean, required
      - `mailboxes` object, nullable, required
        - `read` number, nullable, required
        - `sent_from` number, nullable, required
        - `complete` boolean, required
        - `unavailable_message` string, nullable, required

## Other responses

- `400`: Invalid request parameters
- `401`: Invalid or missing API key
- `403`: Authenticated caller lacks permission for the operation
- `404`: Resource not found
- `429`: Rate limit exceeded. The `ratelimit-*` headers describe the limiter that rejected this request, with its own limit and window, not the API budget that successful responses report. A limiter that reports only a wait sends `Retry-After` alone.

---

[API](https://skmtc.dev/primitive/apis/primitive-api.md) - [All operations](https://skmtc.dev/primitive/apis/primitive-api/llms.txt) - [OpenAPI document](https://skmtc.dev/primitive/apis/primitive-api/revisions/bce409c97acb?raw)
