Skip to content

Certificate templates ​

Generated from core/api/router.go. Edit the router, not this file.

MethodPathWho can call it
GET/api/v1/certificate-templatesAny authenticated user
POST/api/v1/certificate-templatesAdmin
GET/api/v1/certificate-templates/:idAny authenticated user
PUT/api/v1/certificate-templates/:idAdmin
DELETE/api/v1/certificate-templates/:idAdmin

GET /api/v1/certificate-templates ​

Who can call itAny authenticated user
HandlertemplateHandler.List
Display tokenReadable by an unattended screen

Writes are admin-only, where a policy is operator-writable. A policy can only ever refuse more than it did; a template also supplies values and decides whether the requester may set the subject, and that last one is the difference between a template and a way to get a certificate for somebody else's name.

Responses ​

StatusBody
200An object with data (CertificateTemplate[]), total
500{ "error": … }
Example request
bash
curl -X GET 'https://certpilot.example.com/api/v1/certificate-templates' \
  -H 'Authorization: Bearer <token>'

POST /api/v1/certificate-templates ​

Who can call itAdmin
HandlertemplateHandler.Create
Display tokenRefused — not a viewer-safe GET

Request body ​

TemplateInput is what a caller may set on a certificate template. Narrow, rather than binding store.CertificateTemplate. Binding the model is what let a caller choose a policy's identifier and assert when it was written, and it is the same mistake here with twenty-eight columns instead of eight. Identity, authorship, timestamps and the version counter are not the caller's to set. The binding tags carry the CHECK constraints migration 036 put on the table. Without them an unknown subject_mode reaches PostgreSQL and comes back as a raw SQLSTATE 23514, which tells an operator nothing about which value they should have sent.

FieldTypeDescription
slugstringrequiredmaximum 63
namestringrequired
descriptionstring
is_enabledbooleanIsEnabled is a pointer so omitting it leaves the column's default of true, rather than a Go zero value quietly creating every template disabled.
ca_account_idstringrequired
ca_profilestring
subject_modestringone of SUPPLIED, CONSTRAINED
subject_defaultsobject
common_name_ruleCommonNameRule
san_rulesSANRules
allowed_key_typesstring[]
rsa_min_bitsintegerminimum 0
rsa_max_bitsintegerminimum 0
ecdsa_curvesstring[]
csr_requiredboolean
key_custody_requiredstringone of ANY, CERTPILOT, AGENT, EXTERNAL
validity_daysintegerminimum 0
max_validity_daysintegerminimum 0
renew_before_daysintegerminimum 1
auto_renewboolean
require_metadatastring[]
default_environmentstring
default_teamstring
default_tagsstring[]
key_usagestring[]KeyUsage and ExtendedKeyUsage — see #31. Deliberately no binding vocabulary check here: which names are valid depends on the CA this template points at (selfsigned enforces the full x509 vocabulary; ACME and Vault refuse the field entirely), so validate checks it against the account rather than a static list.
extended_key_usagestring[]
basic_constraints_caboolean
extension_passthroughstringone of NONE, LISTED, ALL
passthrough_oidsstring[]
conformancestringConformance — see #30. A pointer so omitting it on create can default by CA type (ENFORCE for a private CA, REPORT otherwise) rather than always falling back to the column's own REPORT default, which would make every new template against a CA this deployment controls silently unenforced until an operator noticed and changed it. — one of ENFORCE, REPORT

Responses ​

StatusBody
201Created
400{ "error": … }
500{ "error": … }
Example request
bash
curl -X POST 'https://certpilot.example.com/api/v1/certificate-templates' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "slug": "<slug>",
  "name": "<name>",
  "ca_account_id": "<ca_account_id>",
  "description": "<description>",
  "is_enabled": false
}'

GET /api/v1/certificate-templates/:id ​

Who can call itAny authenticated user
HandlertemplateHandler.Get
Display tokenReadable by an unattended screen

Parameters ​

NameInDefault
idpathrequired

Responses ​

StatusBody
200Success
404{ "error": … }
500{ "error": … }
· could not read the certificate template
Example request
bash
curl -X GET 'https://certpilot.example.com/api/v1/certificate-templates/<id>' \
  -H 'Authorization: Bearer <token>'

PUT /api/v1/certificate-templates/:id ​

Who can call itAdmin
HandlertemplateHandler.Update
Display tokenRefused — not a viewer-safe GET

Parameters ​

NameInDefault
idpathrequired

Request body ​

TemplateInput is what a caller may set on a certificate template. Narrow, rather than binding store.CertificateTemplate. Binding the model is what let a caller choose a policy's identifier and assert when it was written, and it is the same mistake here with twenty-eight columns instead of eight. Identity, authorship, timestamps and the version counter are not the caller's to set. The binding tags carry the CHECK constraints migration 036 put on the table. Without them an unknown subject_mode reaches PostgreSQL and comes back as a raw SQLSTATE 23514, which tells an operator nothing about which value they should have sent.

FieldTypeDescription
slugstringrequiredmaximum 63
namestringrequired
descriptionstring
is_enabledbooleanIsEnabled is a pointer so omitting it leaves the column's default of true, rather than a Go zero value quietly creating every template disabled.
ca_account_idstringrequired
ca_profilestring
subject_modestringone of SUPPLIED, CONSTRAINED
subject_defaultsobject
common_name_ruleCommonNameRule
san_rulesSANRules
allowed_key_typesstring[]
rsa_min_bitsintegerminimum 0
rsa_max_bitsintegerminimum 0
ecdsa_curvesstring[]
csr_requiredboolean
key_custody_requiredstringone of ANY, CERTPILOT, AGENT, EXTERNAL
validity_daysintegerminimum 0
max_validity_daysintegerminimum 0
renew_before_daysintegerminimum 1
auto_renewboolean
require_metadatastring[]
default_environmentstring
default_teamstring
default_tagsstring[]
key_usagestring[]KeyUsage and ExtendedKeyUsage — see #31. Deliberately no binding vocabulary check here: which names are valid depends on the CA this template points at (selfsigned enforces the full x509 vocabulary; ACME and Vault refuse the field entirely), so validate checks it against the account rather than a static list.
extended_key_usagestring[]
basic_constraints_caboolean
extension_passthroughstringone of NONE, LISTED, ALL
passthrough_oidsstring[]
conformancestringConformance — see #30. A pointer so omitting it on create can default by CA type (ENFORCE for a private CA, REPORT otherwise) rather than always falling back to the column's own REPORT default, which would make every new template against a CA this deployment controls silently unenforced until an operator noticed and changed it. — one of ENFORCE, REPORT

Responses ​

StatusBody
200Success
400{ "error": … }
404{ "error": … }
500{ "error": … }
· could not read the certificate template
Example request
bash
curl -X PUT 'https://certpilot.example.com/api/v1/certificate-templates/<id>' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "slug": "<slug>",
  "name": "<name>",
  "ca_account_id": "<ca_account_id>",
  "description": "<description>",
  "is_enabled": false
}'

DELETE /api/v1/certificate-templates/:id ​

Who can call itAdmin
HandlertemplateHandler.Delete
Display tokenRefused — not a viewer-safe GET

Parameters ​

NameInDefault
idpathrequired

Responses ​

StatusBody
200An object with message (string)
404{ "error": … }
409{ "error": … }
500{ "error": … }
· could not read the certificate template
Example request
bash
curl -X DELETE 'https://certpilot.example.com/api/v1/certificate-templates/<id>' \
  -H 'Authorization: Bearer <token>'