> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.adid.dev/llms.txt.
> For full documentation content, see https://docs.adid.dev/llms-full.txt.

# Create a Schema

##### When to use

No existing schema fits your domain. You need to define the credential's required fields and validation rules before you can issue.

##### Before you begin

* Issuer role.
* A clear specification of the claim (field names, types, constraints).

##### Steps

1. Navigate to `/issuer/schemas` and click **Create schema**.
2. Fill the **Schema metadata** form:
   * **Name** — `OrganisationMembership`.
   * **Version** — `1.0` (semver).
   * **Description** — short purpose statement.
   * **Type URI** — full URI for `@type` field.
3. Define the **JSON Schema body**:
   ```json
   {
     "$schema": "https://json-schema.org/draft/2020-12/schema",
     "type": "object",
     "required": ["membershipId", "tier", "validUntil"],
     "properties": {
       "membershipId": { "type": "string", "minLength": 1 },
       "tier":         { "type": "string", "enum": ["bronze","silver","gold"] },
       "validUntil":   { "type": "string", "format": "date-time" }
     },
     "additionalProperties": false
   }
   ```
4. Toggle **Anchor on chain** if you want the schema hash recorded in the SchemaRegistry (recommended for public-facing schemas; not required for internal use).
5. Click **Create**. The portal calls `POST /api/v1/credentials/schemas` (`vc.go:28`).

##### API & SDK

<table>
  <tr>
    <th>cURL</th>

    <th>TypeScript SDK</th>
  </tr>

  <tr>
    <td>
      ```bash
      curl -X POST https://adid.dev/api/v1/credentials/schemas \
        -H "Authorization: Bearer $ACCESS_TOKEN" \
        -H "Content-Type: application/json" \
        -d '{
          "name":"OrganisationMembership",
          "version":"1.0",
          "issuerDid":"did:adi:0xOrg...",
          "jsonSchema": { "$schema":"https://json-schema.org/draft/2020-12/schema", "type":"object", "required":["membershipId"], "properties":{"membershipId":{"type":"string"}} },
          "anchorOnChain": true
        }'
      ```
    </td>

    <td>
      ```ts
      // Schema CRUD via SDK is planned for v2.1 — for now, call the REST endpoint directly.
      const res = await fetch('https://adid.dev/api/v1/credentials/schemas', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${accessToken}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          name: 'OrganisationMembership',
          version: '1.0',
          issuerDid: 'did:adi:0xOrg...',
          jsonSchema: { /* draft 2020-12 */ },
          anchorOnChain: true,
        }),
      });
      const schema = await res.json();
      ```
    </td>
  </tr>
</table>

##### Verify

The schema appears in `/issuer/schemas`. If anchored, the row shows a chain-link icon; click to view the txHash.

##### Troubleshooting

| Code                        | Cause                                      | Fix                              |
| --------------------------- | ------------------------------------------ | -------------------------------- |
| `400 INVALID_JSON_SCHEMA`   | Body is not valid JSON Schema 2020-12      | Validate locally with `ajv-cli`. |
| `403 ROLE_REQUIRED`         | Caller is not `issuer` or `admin`          | Complete onboarding (§4.1).      |
| `409 SCHEMA_VERSION_EXISTS` | Same `name@version` already created by you | Bump version.                    |

#### 4.2.3. Schema Versioning ##### Overview

IDA enforces **semver-style versioning** on schemas. Once a schema is anchored, its hash is immutable on chain. Changes require a new version (1.0 → 1.1 for backward-compatible additions; 1.0 → 2.0 for breaking changes).

##### Why it matters

Verifiers and issuers must agree on the schema version. A VC issued under `OrganisationMembership@1.0` is **not** automatically valid against a verifier expecting `OrganisationMembership@2.0`. Use the `version` field on the credential's `credentialSchema` reference to make this explicit.

##### How to bump

1. From `/issuer/schemas/<schema>`, click **New version**.
2. Make changes, set `version: "1.1"` or `"2.0"`.
3. Save (and re-anchor if desired).

The platform retains all versions; the issuer chooses which to use at issuance time.

#### 4.2.4. Anchoring a Schema On-Chain ##### When to use

Public-facing or regulated schemas should be anchored so any verifier can check the schema hash matches what's on chain — preventing tampering by a compromised API.

##### Steps

1. From the schema detail page, click **Anchor on chain** (if not already anchored).
2. Wallet prompts for confirmation. Approve.
3. The platform calls `registerSchema(schemaId, hash, version, issuerDid)` on the SchemaRegistry contract.
4. After receipt, the row's status becomes `anchored` with a `txHash`.

##### API

The anchor flag is part of the schema body (see §4.2.2). To anchor an existing schema after creation:

```bash
curl -X POST https://adid.dev/api/v1/credentials/schemas/<id>/anchor \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

##### Verify

Query the SchemaRegistry directly via [§11.3](#schema-registry) — `getSchema(schemaId)` should return your hash.