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

# Verifiable Credentials

> W3C Verifiable Credentials for AI agents — auto-issued on real verification events, plus list, verify, and revoke APIs.

# Verifiable Credentials

Anima's identity layer is built around W3C Verifiable Credentials (VCs): signed, revocable attestations about an agent (for example "this agent's email is verified" or "this org passed billing verification").

<Note>
  **Current status.** Issuance, listing, verification, and revocation are all live. Credentials are issued **automatically on real platform events** — you don't call anything to get them — and the [Agent Card](/identity/agent-cards)'s `verification.level` moves as they land. Revocation is published as a [StatusList2021 bitstring](#revocation-status) you can check without calling us.
</Note>

## How credentials are issued

### Automatically, on platform verification events

| Event | Credentials issued | Issued to |
| - | - | - |
| Email verified (owner completes the OTP on `POST /v1/agent/verify`) | `AnimaEmailVerified` + `AnimaOwnerBound` | Every DID-bearing agent in the org |
| Phone verified (a real number is provisioned) | `AnimaPhoneVerified` | The agent the number was provisioned to |
| Org verified (paid Stripe checkout completes) | `AnimaPaymentCapable` | Every DID-bearing agent in the org |

Issuance is idempotent per (agent, credential type) — retries and repeat verifications don't stack duplicates, and an org that verified before auto-issuance shipped picks its credentials up on its next `/v1/agent/verify` call.

These level-bearing credential types are **platform-reserved**: they cannot be minted through the API, so a card's `verification.level` always reflects something that actually happened.

### Via the API (level-neutral attestations)

```
POST https://api.useanima.sh/v1/agents/{agentId}/credentials
```

Master key required. Issues a signed JWT-VC of a **level-neutral** type (for example `AnimaAddressVerified`) to one of your org's agents. Requests for platform-reserved types are rejected — the API cannot change a card's verification level.

### Issuer model

Credentials are self-issued in v1: signed server-side with the subject agent's own Ed25519 DID key, only on platform events or via the master-key endpoint. `verifyCredential` resolves issuer keys from the agent's DID, so issued VCs verify out of the box. Each credential's `metadata.source` records whether the platform (`platform-auto`) or your master key (`api`) issued it, so consumers can weight them differently. A platform root issuer DID may layer on later.

## Verification levels

The Agent Card's `verification.level` derives from the credential types the agent holds:

| Level | Meaning |
| - | - |
| `basic` | No verification credentials — a fresh, unverified agent. |
| `standard` | A channel was verified: `AnimaEmailVerified` (owner completed the email OTP) or `AnimaPhoneVerified` (a real number was provisioned). |
| `premium` | Standard **plus** org-level verification: `AnimaPaymentCapable` (paid checkout) or `AnimaKYBCompleted` (reserved for a future KYB flow). |

## Working with credentials

### List an agent's credentials

```
GET https://api.useanima.sh/v1/agents/{agentId}/credentials
```

Returns the agent's credential records — type, issuance metadata, `revoked` status, and the compact JWT for each. Self-scoped: an agent key can list only its own credentials; a master key can list any agent's in the org.

### Verify a credential

```
POST https://api.useanima.sh/v1/identity/verify
```

```json theme={null}
{ "jwtVc": "<compact JWT Verifiable Credential>" }
```

Verifies a JWT-encoded VC: signature against the issuer's DID, expiry, and revocation status. Works for externally issued credentials too — the issuer's DID document just has to be resolvable.

### Revoke a credential

```
POST https://api.useanima.sh/v1/agents/{agentId}/credentials/{vcId}/revoke
```

Master key required. Revoked credentials fail verification, stop counting toward the card's verification level, and stay in the list with `revoked: true`. A revoked type can be re-issued.

## Revocation status

Revoked credentials are checkable **without asking Anima**. Every credential carries a [StatusList2021](https://www.w3.org/TR/2023/WD-vc-status-list-20230427/) entry in its `credentialStatus`, naming the list to fetch and the bit to read:

```json theme={null}
"credentialStatus": {
  "id": "https://api.useanima.sh/.well-known/status/{orgId}/{agentId}#3",
  "type": "StatusList2021Entry",
  "statusPurpose": "revocation",
  "statusListIndex": "3",
  "statusListCredential": "https://api.useanima.sh/.well-known/status/{orgId}/{agentId}"
}
```

`GET` that `statusListCredential` URL (unauthenticated) and you get the agent's `StatusList2021Credential` as a signed JWT-VC. To resolve a credential's status yourself:

1. Read `credentialStatus.statusListCredential` from the credential and fetch it.
2. Verify the list's signature against the issuer's public key — it is signed by the same key that signed the credential.
3. Base64url-decode and gunzip `credentialSubject.encodedList` to get the bitstring.
4. Read the bit at `statusListIndex`. **`1` means revoked.**

The published bits are computed from the same source as `POST /v1/identity/verify`, so the two always agree — you can use either.

<Note>
  **Credentials issued before this shipped** carry no `credentialStatus`. They are still revocable, but only through `POST /v1/identity/verify` — a signed JWT cannot be retrofitted with a status entry without changing its signature. Re-issue a credential to get one (issuance is idempotent per type; revoke first if the current one is still live).
</Note>

<Note>
  **Use the `statusListCredential` URL as given.** It resolves on `api.useanima.sh`, not on the `agents.useanima.sh` DID domain. The URL is signed into each credential and never changes for that credential's lifetime.
</Note>

## API Reference

| Endpoint | Method | Description |
| - | - | - |
| `/v1/agents/{agentId}/credentials` | POST | Issue a level-neutral credential (master key) |
| `/v1/agents/{agentId}/credentials` | GET | List an agent's credentials |
| `/v1/identity/verify` | POST | Verify a JWT VC (signature, expiry, revocation) |
| `/v1/agents/{agentId}/credentials/{vcId}/revoke` | POST | Revoke a credential (master key) |
| `/.well-known/status/{orgId}/{agentId}` | GET | The agent's signed StatusList2021 revocation bitstring (public, no auth) |

## Next Steps

* [DID Method](/identity/did-method) -- The signing identity underneath credentials
* [Agent Cards](/identity/agent-cards) -- Where verification state surfaces
* [A2A Protocol](/a2a/overview) -- Signed agent-to-agent requests


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