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

# Presentation presets

> The cornerstone primitive for presentation requests and verification: what to ask for, what comes back, and whose signature counts.

A **presentation preset** is a published, ready-to-use request shape: what credentials to ask for, which attributes come back, and which issuers count as proof. Once published, any verifier refers to it by its identifier (something like `acme:proof-of-degree` or `didx:basic-identity-request`).

To verify something, you pick a preset and create a request from it for a specific user. Think of the preset as a checklist: "show me a credential of this type, with these fields, signed by one of these issuers." The user's wallet receives the checklist, finds credentials that satisfy each line, and returns just the requested fields — already cryptographically validated end to end.

## The shape, end to end

```json theme={null}
{
  "id": "didx:basic-identity-request",
  "author": "didx",
  "code": "basic-identity-request",
  "templateName": "Basic Identity Request",
  "templateDescription": "Standard request for basic identity information",
  "templateCredentials": [
    {
      "format": "sd-jwt-vc",
      "name": "Basic Identity Credential",
      "type": "https://didx.co.za/vct/didx/basic-identity",
      "attributes": {
        "firstName": { "type": "string" },
        "lastName": { "type": "string" }
      },
      "trustedIssuers": [
        {
          "kind": "did",
          "did": "did:web:sarb.gov.za",
          "name": "South African Reserve Bank"
        },
        {
          "kind": "x509",
          "certificate": "-----BEGIN CERTIFICATE-----\nMIIDdzCCAl+gAwIBAgIUJ8vK...PFvKkQ==\n-----END CERTIFICATE-----",
          "name": "Department of Home Affairs"
        }
      ]
    }
  ],
  "verifierConfig": { "signer": "did:web" }
}
```

The top-level fields are mostly metadata: identifier, ownership, and human-readable labels. The request itself lives inside `templateCredentials`.

## Identity and metadata

| Field                   | What it is                                                                                           |
| ----------------------- | ---------------------------------------------------------------------------------------------------- |
| `id`                    | Canonical preset identifier (`<author>:<code>`). This is what verifiers pass as `presetId`.          |
| `author`                | The publisher's tenant alias.                                                                        |
| `code`                  | The slug part of the id, set at creation. Together with `author`, it uniquely identifies the preset. |
| `templateName`          | Human-readable label shown to verifiers browsing the catalogue.                                      |
| `templateDescription`   | One- or two-line summary of what this request is for.                                                |
| `verifierConfig.signer` | How your verifier signs the request payload. `did:web` is the typical choice.                        |

Once published, a preset is immutable; the identifier you choose at creation lives forever. Choose the slug carefully.

## `templateCredentials`: the request itself

This array carries the request itself. Each entry is a **credential the user must produce** for the request to be satisfied. If the array has one entry, one credential is enough; two entries means the user must produce credentials matching both, and so on. Entries can mix formats — one preset can ask for an SD-JWT credential and an mDoc credential in the same request.

A single entry expresses three things: *which kind of credential, which fields from it, and which issuers count as proof*.

### `format` and `type`: which kind of credential

| Field                 | What it is                                                                                                                                                                                                                                                                                                                                       |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `format`              | The credential format the wallet must present. Either `sd-jwt-vc` (selective-disclosure JWT) or `mdoc` (ISO 18013-5 credentials such as mobile driving licences).                                                                                                                                                                                |
| `type`                | The credential **type identifier** the wallet must match. For `sd-jwt-vc` this is the **VCT URL** (e.g. `https://didx.co.za/vct/didx/basic-identity`). For `mdoc` this is the **DocType string** (e.g. `org.iso.18013.5.1.mDL`). The wallet uses this to filter the user's credentials down to the ones that could possibly satisfy the request. |
| `name`, `description` | Human-readable label and explanation of *what kind of credential is being asked for here*. Shown by the wallet during the consent step.                                                                                                                                                                                                          |

The `type` must exactly match the type that issuers put on the credentials they issue. Even a one-character mismatch fails.

### `attributes`: which fields you want back

The shape of the `attributes` map depends on `format`.

**SD-JWT** uses a flat map of attribute name to (currently empty) definition:

```json theme={null}
"attributes": {
  "firstName": { "type": "string" },
  "lastName":  { "type": "string" }
}
```

**mDoc** uses a namespaced map. The outer key is the namespace; each namespace's `properties` carry the attribute names and an `intentToRetain` flag:

```json theme={null}
"attributes": {
  "org.iso.18013.5.1": {
    "properties": {
      "given_name":  { "intentToRetain": false },
      "family_name": { "intentToRetain": false },
      "portrait":    { "intentToRetain": false }
    }
  }
}
```

`intentToRetain` is the verifier's signal to the holder about whether it intends to **store** the attribute after presentation (privacy-relevant under ISO 18013-5). Set `true` when you genuinely need to retain the value (e.g. record-keeping); set `false` for transient checks (e.g. age gate).

In both formats, only the attributes listed here are requested. The user's wallet uses selective disclosure to reveal just those, leaving anything else in the credential hidden.

### `trustedIssuers`: which issuers count as proof

The issuers whose signature on this credential type counts as proof. Even if the user holds a credential of the right type, it only counts if it's signed by an issuer in this list. This is the part that makes verification with verifiable credentials powerful: you're not only asking *what* the user has, you're declaring *which issuers* you accept it from.

Each entry describes an issuer **directly**, with a human-readable `name`:

```json theme={null}
{ "kind": "did",  "did": "did:web:sarb.gov.za", "name": "South African Reserve Bank" }
{ "kind": "x509", "certificate": "-----BEGIN CERTIFICATE-----\nMIIDdzCCAl+gAwIBAgIUJ8vK...PFvKkQ==\n-----END CERTIFICATE-----", "name": "Department of Home Affairs" }
```

Two flavours:

* **`kind: "did"`.** A Decentralised Identifier the issuer publishes (e.g. `did:web:sarb.gov.za`, hosted at `https://sarb.gov.za/.well-known/did.json`). The wallet resolves the DID to fetch the issuer's signing key.
* **`kind: "x509"`.** A PEM-encoded X.509 certificate. Used for issuers that operate via traditional PKI (common for ISO 18013-5 mDLs).

The `name` is what the wallet shows the user when asking for consent. Choose one the user will recognise.

<Warning>
  **Empty `trustedIssuers` means any issuer is trusted.** If you leave the list empty (or omit it), the verifier accepts
  a credential of the right type from *any* issuer, including issuers the user has registered themselves. This is almost
  never what you want. For real verifications, list the specific issuers whose credentials count.
</Warning>

## What happens at presentation time

When a verifier creates a presentation request from a preset, the wallet on the other end uses the preset's structure directly:

1. The verifier creates a presentation request (passing `presetId`).
2. The user's wallet receives the request and reads each entry's `type`, `attributes`, and `trustedIssuers`.
3. For each entry, the wallet resolves `trustedIssuers` (fetching DID documents or validating cert chains) to determine which signing keys are acceptable.
4. It then **only shows the user credentials of the right `type` signed by one of those issuers**. Anything else is filtered out before the user sees it.
5. The user picks the credentials they want to share, consents, and the wallet returns the requested attributes.
6. When the verifier receives the response, the issuer chain has already been validated end to end. No re-verification is needed on the verifier's side.

## Two paths

<CardGroup cols={2}>
  <Card title="Browse a presentation preset" icon="magnifying-glass" href="/products/didx-me/guides/verifiers/browse-presentation-presets">
    Find a preset already published by DIDx or another publisher and use it as-is. The trust list comes baked in.
  </Card>

  <Card title="Create a presentation preset" icon="pen-to-square" href="/products/didx-me/guides/verifiers/create-presentation-preset">
    Publish your own request shape (including the trusted issuers) so it can be referenced by name.
  </Card>
</CardGroup>

## When a preset isn't enough

If no preset matches your use case, you can define a one-off [custom presentation template](/products/didx-me/guides/verifiers/create-presentation-template) instead and reference your tenant's trusted-entity records by id. This is the exception, not the rule; most integrations don't need it.
