---
title: "Issue Certificates"
description: "Use the X.509 Certificate Service to issue IACA root certificates, Document Signer certificates, and generic X.509 certificates."
stack: "Enterprise Stack (commercial) — version 0.21.0"
stack_version: "0.21.0"
stack_comparison: https://docs.walt.id/community-vs-enterprise.md
canonical_url: https://docs.walt.id/enterprise-stack/services/x509-service/issue-certificates
generated: 2026-07-20
---
# Issue Certificates

Use the X.509 Certificate Service to issue IACA root certificates, Document Signer certificates, and generic X.509 certificates.

Service reference: [Swagger API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/Service%20%7C%20X.509%20Certificate%20Service)

**Note:**

If one or more [X.509 Store services](https://docs.walt.id/enterprise-stack/services/x509-store-service/overview.md) are attached, the service uses one shared `storedCertificateId` child ID across all attached stores. When you omit `storedCertificateId`, the service generates a UUID automatically. If no store is attached, the field is ignored and `storedCertificateIds` is omitted from the response.

## Shared Path Parameters

- `orgID`: When performing operations within an organization, use the organization's Base URL or another valid host alias. For example, if your organization is named `test`, your default Base URL will be `test.enterprise-sandbox.waltid.dev` when using the sandbox environment.
- `target`: The full X.509 Certificate service path (`{organizationID}.{tenantID}.{x509ServiceID}`), for example `test.tenant1.x509-service-1`.

## Create an IACA certificate

**Option: CURL**

Endpoint: `/v1/{target}/x509-service-api/iso/iacas` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/Service%20%7C%20X.509%20Certificate%20Service)

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/x509-service-api/iso/iacas' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "storedCertificateId": "iaca-prod-2026-q1",
  "certificateData": {
    "country": "US",
    "commonName": "Example IACA",
    "issuerAlternativeNameConf": {
      "uri": "https://iaca.example.com"
    }
  },
  "vicalEntryComplementaryMetadata": {
    "docType": ["org.iso.18013.5.1.mDL"],
    "certificateProfile": ["org.iso.18013.5.1.iaca"]
  },
  "iacaKeyDesc": {
    "type": "kms-hosted-key-descriptor",
    "keyIdPath": "test.tenant1.kms1.secp256r1"
  }
}'
```

**Body Parameters**

- `certificateData`: Subject and validity data for the generated IACA certificate.
- `iacaKeyDesc`: Signing key descriptor. Use either `kms-hosted-key-descriptor` or `jwk-encoded-key-descriptor`.
- `storedCertificateId`: Optional child certificate ID used when one or more X.509 Store dependencies are attached. The response returns the resulting full stored certificate paths in `storedCertificateIds`.
- `vicalEntryComplementaryMetadata`: Optional metadata. When provided and stores are attached, the issued IACA is stored as a VICAL entry; otherwise it is stored as a generic certificate.

**Example Response**

```json
{
  "certificatePEM": "-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----",
  "storedCertificateIds": [
    "test.tenant1.x509-store-1.iaca-prod-2026-q1"
  ],
  "certificateData": {
    "country": "US",
    "commonName": "Example IACA",
    "notBefore": "<generated-timestamp>",
    "notAfter": "<generated-timestamp>",
    "issuerAlternativeNameConf": {
      "uri": "https://iaca.example.com"
    }
  }
}
```

**Response Codes**

- `200` - IACA certificate issued successfully.

**Note:**

If no X.509 Store dependency is attached, `storedCertificateId` is ignored on the request and `storedCertificateIds` is omitted from the response.

## Create a Document Signer certificate

**Option: CURL**

Endpoint: `/v1/{target}/x509-service-api/iso/document-signers` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/Service%20%7C%20X.509%20Certificate%20Service)

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/x509-service-api/iso/document-signers' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "storedCertificateId": "ds-mainline-2026-01",
  "iacaSigner": {
    "type": "iaca-cert-data-descriptor",
    "iacaKeyDesc": {
      "type": "kms-hosted-key-descriptor",
      "keyIdPath": "test.tenant1.kms1.iaca-secp256r1"
    },
    "certificateData": {
      "country": "US",
      "commonName": "Example IACA",
      "notBefore": "2025-05-28T12:23:01Z",
      "notAfter": "2040-05-24T12:23:01Z",
      "issuerAlternativeNameConf": {
        "uri": "https://iaca.example.com"
      }
    }
  },
  "certificateData": {
    "country": "US",
    "commonName": "Example DS",
    "crlDistributionPointUri": "https://crl-example.com"
  },
  "dsPublicKeySource": {
    "type": "key-descriptor",
    "keyDescriptor": {
      "type": "kms-hosted-key-descriptor",
      "keyIdPath": "test.tenant1.kms1.ds-secp256r1"
    }
  }
}'
```

**Body Parameters**

- `iacaSigner`: Describes the IACA used to issue the Document Signer certificate. Use either `iaca-cert-data-descriptor` or `iaca-pem-cert-descriptor`.
- `certificateData`: Subject and validity data for the generated Document Signer certificate.
- `dsPublicKeySource`: Source of the Document Signer's public key. Use either:
  - `key-descriptor`: Direct key reference via `kms-hosted-key-descriptor` or `jwk-encoded-key-descriptor`.
  - `csr`: CSR PEM string for CSR-based issuance (see [CSR Workflows](https://docs.walt.id/enterprise-stack/services/x509-service/csr-workflows.md)).
- `dsKeyDescriptor`: Legacy field for direct key descriptor. Use `dsPublicKeySource` for new integrations.
- `storedCertificateId`: Optional child certificate ID used when one or more X.509 Store dependencies are attached. The response returns the resulting full stored certificate paths in `storedCertificateIds`.

**Example Response**

```json
{
  "certificatePEM": "-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----",
  "storedCertificateIds": [
    "test.tenant1.x509-store-1.ds-mainline-2026-01"
  ],
  "certificateData": {
    "country": "US",
    "commonName": "Example DS",
    "notBefore": "<generated-timestamp>",
    "notAfter": "<generated-timestamp>",
    "crlDistributionPointUri": "https://crl-example.com"
  }
}
```

**Response Codes**

- `200` - Document Signer certificate issued successfully.

If a provided `storedCertificateId` already exists in any attached X.509 Store, or if any attached store write fails, the issuance request fails.

## Create a generic certificate

Generic certificates provide full control over X.509 certificate attributes including subject name, key usage, extended key usage, validity period, and CA constraints. They can be self-signed or signed by a CA key.

**Option: CURL**

Endpoint: `/v1/{target}/x509-service-api/certificate` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/Service%20%7C%20X.509%20Certificate%20Service)

**Self-signed leaf certificate**

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/x509-service-api/certificate' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "storedCertificateId": "generic-leaf-01",
  "certificateData": {
    "subjectName": {
      "commonName": "Example Leaf",
      "country": "US",
      "organizationName": "Example Org"
    },
    "isCertificateAuthority": false,
    "keyUsage": ["DigitalSignature"]
  },
  "subjectPublicKeySource": {
    "type": "key-descriptor",
    "keyDescriptor": {
      "type": "kms-hosted-key-descriptor",
      "keyIdPath": "test.tenant1.kms1.leaf-secp256r1"
    }
  },
  "issuer": {
    "type": "self-signed"
  }
}'
```

**CA-signed certificate**

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/x509-service-api/certificate' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "storedCertificateId": "generic-intermediate-01",
  "certificateData": {
    "subjectName": {
      "commonName": "Example Intermediate CA",
      "country": "US"
    },
    "isCertificateAuthority": true,
    "pathLengthConstraint": 0,
    "keyUsage": ["KeyCertSign", "CRLSign"]
  },
  "subjectPublicKeySource": {
    "type": "key-descriptor",
    "keyDescriptor": {
      "type": "kms-hosted-key-descriptor",
      "keyIdPath": "test.tenant1.kms1.intermediate-secp256r1"
    }
  },
  "issuer": {
    "type": "ca-signed",
    "issuerKeyDescriptor": {
      "type": "kms-hosted-key-descriptor",
      "keyIdPath": "test.tenant1.kms1.root-secp256r1"
    }
  }
}'
```

**Body Parameters**

- `certificateData`: Certificate attributes including subject name, validity, CA constraints, and key usage.
  - `subjectName`: Distinguished name fields (`commonName`, `country`, `organizationName`, etc.).
  - `issuerName`: Optional issuer distinguished name. Defaults to subject name for self-signed certificates.
  - `notBefore` / `notAfter`: Optional validity period. Defaults to now and 365 days from now.
  - `isCertificateAuthority`: Set to `true` for CA certificates.
  - `pathLengthConstraint`: Optional path length for CA certificates.
  - `keyUsage`: Array of key usage values (`DigitalSignature`, `KeyCertSign`, `CRLSign`, etc.).
  - `extendedKeyUsageOids`: Optional array of extended key usage OIDs.
  - `subjectAlternativeNames`: Optional SAN values (`dnsNames`, `uris`, `emails`, `ipAddresses`).
  - `crlDistributionPointUri`: Optional CRL distribution point.
- `subjectPublicKeySource`: Source of the subject's public key. Use either:
  - `key-descriptor`: Direct key reference via `kms-hosted-key-descriptor` or `jwk-encoded-key-descriptor`.
  - `csr`: CSR PEM string for CSR-based issuance (see [CSR Workflows](https://docs.walt.id/enterprise-stack/services/x509-service/csr-workflows.md)).
- `issuer`: Issuer configuration. Use either:
  - `self-signed`: The certificate is self-signed using the subject key.
  - `ca-signed`: The certificate is signed by a CA key specified in `issuerKeyDescriptor`.
- `storedCertificateId`: Optional child certificate ID for storage in attached X.509 Stores.

**Example Response**

```json
{
  "storedCertificateIds": ["test.tenant1.x509-store-1.generic-leaf-01"],
  "certificatePEM": "-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----",
  "certificateData": {
    "subjectName": {
      "commonName": "Example Leaf",
      "country": "US",
      "organizationName": "Example Org"
    },
    "issuerName": {
      "commonName": "Example Leaf",
      "country": "US",
      "organizationName": "Example Org"
    },
    "notBefore": "<generated-timestamp>",
    "notAfter": "<generated-timestamp>",
    "isCertificateAuthority": false,
    "keyUsage": ["DigitalSignature"],
    "publicKeyJwk": {
      "kty": "EC",
      "crv": "P-256",
      "x": "...",
      "y": "..."
    }
  }
}
```

**Response Codes**

- `200` - Generic certificate issued successfully.

**Note:**

Self-signed certificates require a `key-descriptor` subject public key source since the same key is used for signing. CSR-based issuance requires a `ca-signed` issuer.
