CSR Workflows
The X.509 Certificate Service supports PKCS#10 Certificate Signing Request (CSR) creation and CSR-based certificate issuance. This enables proof-of-possession workflows where the certificate requester proves control of the private key.
Service reference: Swagger API Reference
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 namedtest, your default Base URL will betest.enterprise-sandbox.waltid.devwhen using the sandbox environment.target: The full X.509 Certificate service path ({organizationID}.{tenantID}.{x509ServiceID}), for exampletest.tenant1.x509-service-1.
Create a CSR
Create a PKCS#10 Certificate Signing Request. The CSR is signed by the subject key, proving possession of the private key. The returned CSR PEM can be submitted to an external CA or used as a subject public key source when creating certificates through this service.
Endpoint: /v1/{target}/x509-service-api/csrs | API Reference
Example Request
curl -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/x509-service-api/csrs' \
-H 'accept: application/json' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"type": "generic",
"subjectKeyDescriptor": {
"type": "kms-hosted-key-descriptor",
"keyIdPath": "test.tenant1.kms1.leaf-secp256r1"
},
"subjectName": {
"commonName": "Example Leaf",
"country": "US",
"organizationName": "Example Org"
},
"subjectAlternativeNames": {
"dnsNames": ["leaf.example.com"]
}
}'
Body Parameters
type: String - Set to"generic"for generic CSR.subjectKeyDescriptor: Object - Key descriptor for the subject key.type: String - Descriptor type. Use"kms-hosted-key-descriptor"for keys stored in a KMS service or"jwk-encoded-key-descriptor"for directly provided JWK keys.keyIdPath: String - (For KMS-hosted keys) The full key path in format{organizationID}.{tenantID}.{kmsServiceID}.{keyID}, e.g.test.tenant1.kms1.leaf-secp256r1.
subjectName: Object - Distinguished name fields (commonName,country,organizationName,stateOrProvinceName,localityName,organizationalUnitName).subjectAlternativeNames: Object (optional) - SAN values (dnsNames,uris,emails,ipAddresses).
Example Response
{
"csrPEM": "-----BEGIN CERTIFICATE REQUEST-----
MIIB...
-----END CERTIFICATE REQUEST-----",
"csrData": {
"subjectName": {
"commonName": "Example Leaf",
"country": "US",
"organizationName": "Example Org"
},
"subjectAlternativeNames": {
"dnsNames": ["leaf.example.com"]
},
"publicKeyJwk": {
"kty": "EC",
"crv": "P-256",
"x": "q0xi21uudhkC1QMykfYryN9bcDx480iJLSaRI05CWgY",
"y": "NhD-09xqrUgE2-qSt8g5imePgKPPNVpYoHmsTL2f4io"
}
}
}
Response Codes
200- CSR created successfully.
The CSR endpoint is stateless. The service does not persist CSR state. Store the returned csrPEM for later use when creating certificates.
Issue a certificate from a CSR
Both generic certificates and Document Signer certificates can be issued using a CSR as the subject public key source. This workflow verifies proof-of-possession before issuing the certificate.
Generic certificate from CSR
Endpoint: /v1/{target}/x509-service-api/certificate | API Reference
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-from-csr",
"certificateData": {
"subjectName": {
"commonName": "Example Leaf From CSR",
"country": "US"
},
"keyUsage": ["DigitalSignature"]
},
"subjectPublicKeySource": {
"type": "csr",
"csrPEM": "-----BEGIN CERTIFICATE REQUEST-----
MIIB...
-----END CERTIFICATE REQUEST-----"
},
"issuer": {
"type": "ca-signed",
"issuerKeyDescriptor": {
"type": "kms-hosted-key-descriptor",
"keyIdPath": "test.tenant1.kms1.iaca-secp256r1"
}
}
}'
Body Parameters
subjectPublicKeySource: Object - Source of the subject's public key.type: String - Set to"csr"for CSR-based issuance.csrPEM: String - The CSR in PEM format (begins with-----BEGIN CERTIFICATE REQUEST-----).
issuer: Object - Issuer configuration. Must beca-signedfor CSR-based issuance. Self-signed certificates cannot use CSR input.type: String - Set to"ca-signed".issuerKeyDescriptor: Object - Key descriptor for the CA signing key.type: String - Descriptor type. Use"kms-hosted-key-descriptor"for keys stored in a KMS service or"jwk-encoded-key-descriptor"for directly provided JWK keys.keyIdPath: String - (For KMS-hosted keys) The full key path in format{organizationID}.{tenantID}.{kmsServiceID}.{keyID}, e.g.test.tenant1.kms1.iaca-secp256r1.
- Other parameters are the same as generic certificate creation.
Response Codes
200- Certificate issued successfully.
Document Signer certificate from CSR
Endpoint: /v1/{target}/x509-service-api/iso/document-signers | API Reference
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-from-csr-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": "csr",
"csrPEM": "-----BEGIN CERTIFICATE REQUEST-----
MIIB...
-----END CERTIFICATE REQUEST-----"
}
}'
Body Parameters
dsPublicKeySource: Settypetocsrand provide thecsrPEMstring. This replaces the legacydsKeyDescriptorfield.- Other parameters are the same as Document Signer certificate creation.
The
dsKeyDescriptorfield is still supported for backward compatibility, butdsPublicKeySourceis preferred for new integrations. The two fields are mutually exclusive.
Response Codes
200- Document Signer certificate issued successfully.
End-to-end CSR workflow example
This example demonstrates a complete CSR-based issuance workflow:
- Create a CSR using a key hosted in the KMS
- Submit the CSR to create a CA-signed certificate
# Step 1: Create a CSR
CSR_RESPONSE=$(curl -s -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/x509-service-api/csrs' \
-H 'accept: application/json' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"type": "generic",
"subjectKeyDescriptor": {
"type": "kms-hosted-key-descriptor",
"keyIdPath": "test.tenant1.kms1.leaf-secp256r1"
},
"subjectName": {
"commonName": "Example Leaf",
"country": "US"
}
}')
# Extract the CSR PEM (requires jq)
CSR_PEM=$(echo "$CSR_RESPONSE" | jq -r '.csrPEM')
# Step 2: Create a certificate from the CSR
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 "{
\"certificateData\": {
\"subjectName\": {
\"commonName\": \"Example Leaf\",
\"country\": \"US\"
},
\"keyUsage\": [\"DigitalSignature\"]
},
\"subjectPublicKeySource\": {
\"type\": \"csr\",
\"csrPEM\": $(echo "$CSR_PEM" | jq -Rs .)
},
\"issuer\": {
\"type\": \"ca-signed\",
\"issuerKeyDescriptor\": {
\"type\": \"kms-hosted-key-descriptor\",
\"keyIdPath\": \"test.tenant1.kms1.ca-secp256r1\"
}
}
}"
Use cases
External CA integration
Generate CSRs through the X.509 Certificate Service and submit them to external Certificate Authorities. The CSR proves possession of the private key stored in your KMS.
Delegated key management
Allow external parties to generate their own key pairs and submit CSRs. The X.509 Certificate Service can then issue certificates using the CSR's public key while the private key remains with the requester.
Compliance workflows
Some compliance frameworks require proof-of-possession during certificate issuance. CSR-based workflows satisfy this requirement by having the certificate requester sign the CSR with their private key.
