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

# API keys

> Give each service or partner its own API key with only the access it needs: per-resource read or write, workflow and status limits, an IP allowlist, an expiry date and instant revoke.

export const AgentPromptAccordion = ({prompt, title = "AI Agent Integration Prompt"}) => {
  const [copied, setCopied] = React.useState(false);
  const handleCopy = e => {
    e.stopPropagation();
    if (!prompt) return;
    navigator.clipboard.writeText(prompt.trim()).then(() => {
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    });
  };
  const agents = ["Claude Code", "Codex", "Cursor", "Devin", "Windsurf", "GitHub Copilot"];
  return <div className="didit-agent-card">
      {}
      <div className="didit-agent-titlebar">
        <div className="didit-agent-dots" aria-hidden="true">
          <span className="didit-agent-dot didit-agent-dot-red"></span>
          <span className="didit-agent-dot didit-agent-dot-yellow"></span>
          <span className="didit-agent-dot didit-agent-dot-green"></span>
        </div>
        <span className="didit-agent-filename">{title}</span>
        <button type="button" className={`didit-agent-copy ${copied ? "didit-agent-copy-copied" : ""}`} onClick={handleCopy} title="Copy prompt to clipboard" aria-label={copied ? "Copied!" : "Copy prompt to clipboard"}>
          {copied ? <>
              <svg width="13" height="13" viewBox="0 0 16 16" fill="none">
                <path d="M3 8.5l3.5 3.5L13 4" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
              <span>Copied</span>
            </> : <>
              <svg width="13" height="13" viewBox="0 0 16 16" fill="none">
                <rect x="5" y="5" width="9" height="9" rx="1.5" stroke="currentColor" strokeWidth="1.5" />
                <path d="M11 5V3.5A1.5 1.5 0 0 0 9.5 2h-6A1.5 1.5 0 0 0 2 3.5v6A1.5 1.5 0 0 0 3.5 11H5" stroke="currentColor" strokeWidth="1.5" />
              </svg>
              <span>Copy</span>
            </>}
        </button>
      </div>

      {}
      <pre className="didit-agent-body"><code>{prompt.trim()}</code></pre>

      {}
      <div className="didit-agent-footer">
        <span className="didit-agent-footer-label">Paste into</span>
        <div className="didit-agent-chips">
          {agents.map(name => <span key={name} className="didit-agent-chip">{name}</span>)}
        </div>
      </div>
    </div>;
};

<AgentPromptAccordion
  title="Scoped API keys prompt"
  prompt={`# Goal - call Didit with a scoped API key

Every application has a primary secret with full access, and any number of named API keys.
A named key carries its own access: read or write per resource, optional limits, an optional IP allowlist and an optional expiry date.
Keys are created, edited, rotated and revoked in the Business Console (Developers -> API keys); there is no API to manage them.

## Sending the key

\`\`\`bash
curl https://verification.didit.me/v3/session/$SESSION_ID/decision/ \\
-H "x-api-key: $DIDIT_API_KEY"
\`\`\`

Read the key from an environment variable or a secrets manager, never from source code.

## What each answer means

| Status | Meaning |
|---|---|
| 401 | The key is missing, wrong, revoked or expired |
| 403 | The key has no access to this resource or action, or the request came from an address outside its IP list |
| 404 | The session is outside the key's workflows or statuses, so to this key it does not exist |

A key without media access receives decisions with every image, video and PDF URL set to null, and gets 403 on PDF reports.
A key without sessions write receives session_url and session_token as null.

## Resources

sessions, decisions, media (read only), users, businesses, transactions, workflows, webhooks, applications, analytics (read only), api-keys.
Read covers GET requests, write covers POST, PUT, PATCH and DELETE.
Standalone checks (face match, ID verification, AML screening and the other /v3 standalone APIs) need sessions write.

## Limits

- workflow_ids: only sessions of these workflows are visible, and sessions can only be created with them.
- approved sessions only: declined, in-review and unfinished sessions are hidden.
- A key with either limit cannot have access to users, businesses, transactions or analytics.

## Rotation

Rotating a key returns a new secret once; the previous secret keeps working for 24 hours.
`}
/>

Every application starts with a **primary secret** that has full access to everything the application can do.
You can add **named API keys** next to it, one per service or partner, each with only the access it needs.
Give your payout provider a key that reads approved sessions of one workflow and can't change anything, keep a separate key for your backend, and revoke either one without touching the other.

<Info>
  Keys created before scoped access existed keep full access.
  Nothing changes for them until you edit their access.
</Info>

***

## Where to find them

In the [**Business Console**](https://business.didit.me), select your application and open **Developers -> API keys**.

The list shows every key of the application with its status, its requests over the last 30 days, who created it, its access and when it was last used.
Click a key to preview it on the right, or open its full page for usage, access, recent requests, a quickstart snippet and its activity.

Keys belong to one application and work only for it.
A key has the application's environment: keys of a sandbox application never create billed verifications.

***

## Create a key

<Steps>
  <Step title="Detail">
    Name the key after the service that will use it, and choose when it expires: never, in 30 days, 90 days, a year, or on a date you pick.
    An expired key stops working at the end of that day, UTC.
  </Step>

  <Step title="Access">
    Start from a preset, then fine-tune it per resource.
    The key can never do more than this.
  </Step>

  <Step title="Review">
    The console spells out what the key can do and what it can't, before you hand it out.
  </Step>

  <Step title="Secret key">
    Copy the secret and store it in your secrets manager.
    This is the only time the full secret is shown.
    If you lose it, rotate the key to get a new one.
  </Step>
</Steps>

### Presets

| Preset | Access |
| - | - |
| **Full access** | Every resource, read and write, including other API keys. For your own backend. |
| **Read only** | Sessions and decisions, with media optional. It can't create, change or delete anything. For a partner that needs results. |
| **Custom** | You choose None, Read or Write for each resource. |

### Resources

Read covers `GET` requests on a resource; write also covers `POST`, `PUT`, `PATCH` and `DELETE`.

| Resource | Read | Write |
| - | - | - |
| **Sessions** | List and open sessions | Create, update and delete sessions, import sessions, and run standalone checks (face match, ID verification, AML screening and the other standalone APIs) |
| **Decisions** | Results, risk scores, extracted data and AML screening history | Approve, decline or send to review, and change feature and AML hit statuses |
| **Media** | ID images, selfies, videos and PDF reports | - |
| **People** (`users`) | End users and everything verified about them | Create, update and delete users, and their monitoring |
| **Companies** (`businesses`) | Business profiles, their documents and owners | Create, update and delete businesses, and their monitoring |
| **Transactions** | Transactions, alerts, rules, monitoring events, Travel Rule data and wallet screening | Send transactions and events, and change their status |
| **Workflows** | Workflows, questionnaires, lists and blocklists | Create and edit them |
| **Webhooks** | Endpoints, and deliveries (with **Decisions** read, since a delivery carries the session payload it sent) | Add, edit and delete endpoints, and resend deliveries |
| **Application settings** (`applications`) | Customization and balance | Change customization and top up the balance |
| **Analytics** | Metrics and report exports | - |
| **API keys** | Reserved for key management | Reserved for key management |

A key with custom access works on the public API: the session, user, business, transaction, workflow and webhook endpoints, and the standalone checks.
Endpoints that only the Business Console uses answer `403` to it; they need a full-access key.

A key without **Media** read receives session decisions with every image, video and PDF URL set to `null`, and PDF report endpoints answer `403`.
A key without **Sessions** write never receives a session's verification link or session token, since whoever holds them can complete the verification as the end user: those fields come back as `null`.

### Limits

| Limit | What it does |
| - | - |
| **Workflows** | The key only sees sessions of the workflows you pick, and can only create sessions with them. Any other session answers `404`, as if it did not exist. |
| **Only approved sessions** | Declined, in-review and unfinished sessions stay hidden from the key. |
| **IP addresses** | The key only works from the addresses or CIDR ranges you list (up to 20, IPv4 or IPv6). Requests from any other address answer `403`. |
| **Expires** | After this date every request with the key answers `401`. |

A key limited to some workflows or to approved sessions works on the session endpoints, where the limit can be applied.
It can't have access to people, companies, transactions or analytics, and it can't run standalone checks.

***

## How the API answers a scoped key

| Status | Meaning |
| - | - |
| **401** | The key is missing, wrong, revoked or expired. |
| **403** | The key has no access to this resource or action, or the request came from an address outside its IP list. |
| **404** | The session is outside the key's workflows or statuses. |

Session lists only return the sessions the key's limits allow.

***

## Edit access

Open a key's menu, its preview or its page and choose **Edit access**.
Change the preset, resources, limits or expiry, then review only what changes, before and after.
The secret stays the same, so nothing needs redeploying, and the new access applies within a minute.

The primary secret always has full access and can't be edited.

***

## Rotate a key

Rotating replaces a key's secret.
The new secret is shown once, and the current secret keeps working for **24 hours** so you can deploy the new one without downtime.
After that, every request with the old secret answers `401`.

The primary secret is rotated the same way, with the same 24-hour overlap.

***

## Revoke a key

Revoking stops a key at once: every request made with it answers `401`.
It cannot be undone.
The primary secret can't be revoked; rotate it instead.

***

## Usage and audit trail

Each key shows its requests over the last 30 days, its error rate and latency, and its latest requests with their status codes, including the ones its limits refused.

Every call made with an API key appears in the organization's [audit logs](/console/audit-logs) with the name of the key that made it.

***

## Who can manage keys

Managing API keys needs the **API keys** permission: read to see them, write to create, edit, rotate and revoke them.
See [Roles and permissions](/console/roles-permissions).


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