(DC) CERTInext REST API (Practical Guide)

(DC) CERTInext REST API (Practical Guide)

CERTInext REST API v2 — Practical Guide

What the API can do, organized by task. Verified live against the production account (1251749675) as a Manager on 2026-07-21.

  • Base URL: https://us-api.certinext.io

  • All paths below are prefixed with: /api/certinext/v2

  • Auth: OAuth 2.0 client-credentials → short-lived Bearer JWT (see below).

Legend

  • ✅ Verified — called live and returned real data (Manager account).

  • 🧩 Confirmed (state-changing) — exists / exercised by the official certinext Python client, but not re-fired here because it writes.

  • ⛔ Not available via REST — console-only, or missing (see Gaps).

  • Unless noted, everything verified here works with a Manager role.

Verification: every ✅ row was fetched live on 2026-07-21 (Manager, prod account 1251749675). Endpoint paths cross-checked against the official certinext Python client. 🧩 rows are exercised by that client but not re-fired here because they change state. No state-changing calls were made while producing this document.

1. Authenticate

Op

Method + path

Notes

Op

Method + path

Notes

Get token

POST /oauth/token

✅ grant_type=client_credentialsclient_id=<account #>client_secret=<secret> → access_token (1 h).

Who am I

GET /auth/me

✅ Returns accountNumberauthType. Good health check.

# token (form-encoded); then use: Authorization: Bearer <access_token> curl -s https://us-api.certinext.io/oauth/token \ -d grant_type=client_credentials -d client_id=1251749675 -d client_secret=****

2. Discover inventory (orgs, groups, domains)

Operation

Method + path

Status

Useful for

Operation

Method + path

Status

Useful for

List organizations

GET /organizations

The org records you can issue under (4 in this account). Fields incl. organizationNumberorganizationNameorganizationStatusIdisPreVettingOrgvalidationFor.

Organization detail

GET /organizations/{orgNumber}

Full org: orgRepresentatives, address, validationStatusIdvalidationFordomainssubscriberAgreement.

List groups

GET /groups

✅ ⚠️

Group → organization bindings (groupNumbergroupName, org details). Caveat: returned a subset of groups vs. the console; and it does not return a group's domain permit-list (see Gaps).

List domains

GET /domains

The domain inventory (2,454 entries). Offset/limit paging; response shape content[] + totalElements + totalPages.

Domain detail

GET /domains/{domainId}

One domain: domainNamestatusdcvStatusdcv{}organizationNamecreatedAt.

GET /domains paging & filters (0-based offsetlimit ≤ … ; content/totalElements): search (name), domainStatusdcvStatusdcvMethod, created-date range.

curl -s -H "Authorization: Bearer $TOK" \ "https://us-api.certinext.io/api/certinext/v2/domains?offset=0&limit=50"

3. Products (what you're allowed to issue)

Op

Method + path

Status

Notes

Op

Method + path

Status

Notes

List products

GET /catalog/products

35 products across DV / OV / EV / IGTF-OV families (base, 30/90-day, Wildcard, UCC combos). Grouped by category → each category has an inner products[].

Product custom fields

GET /catalog/products/{productCode}/custom-fields

Fields a given product requires on the order.

This answers "are DV/EV available?" — yes, all of DV, OV, EV, and IGTF-OV products exist in production. A group can only use the products on its Allow Products list.

4. Request / issue a certificate

Op

Method + path

Status

Notes

Op

Method + path

Status

Notes

Create SSL order

POST /ssl-certificates

🧩

Body carries product, CSR, organization, domains, custom fields. Returns an order id.

Order / cert detail

GET /ssl-certificates/{orderId}

orderIdstatusorderStatecertificateStatedomainrequestorcsrSubmittedverificationsThis is where you track a specific order and pull the issued cert.

Download issued cert

(from the order detail once certificateState is issued)

🧩

The official certinext client exposes download() / download_chain() off the order.

Two issuance paths: (a) ACME (EAB) — the normal, automated path; (b) REST POST /ssl-certificates for scripted, non-ACME issuance. Either way the order still passes the approval gate below.

5. Search certificates & check status ← very useful

Op

Method + path

Status

Notes

Op

Method + path

Status

Notes

Order / certificate history

GET /reports/orders

The cert search/inventory endpoint. 1-based page/size (size ≤ 100); optional status filter. Shape content[] + totalElements + totalPages.

Transaction ledger

GET /reports/ledger

Billing/transaction history (accessible to a Manager; often a Finance view).

Each /reports/orders row is rich — you can answer real questions without opening the portal:

orderNumbercertificateStatus (e.g. "Pending for Approver", "Issued"), orderStatus ("Order Accepted"…), originator ("ACME"/"CERTInext"), productCodedomainNamegroupNumbercertificateSerialNumbercertificateExpiryDateissuerCAorderDatetagsrequestNumber.

# All orders (paged): curl -s -H "Authorization: Bearer $TOK" \ "https://us-api.certinext.io/api/certinext/v2/reports/orders?page=1&size=100" # By status (client examples: issued, expired): ".../reports/orders?page=1&size=100&status=issued"

Useful things this answers:

  • "What's stuck waiting for approval?" → filter rows where certificateStatus == "Pending for Approver".

  • "What's expiring / expired?" → status=expired, or sort rows by certificateExpiryDate.

  • "Which group/product issued this?" → groupNumber + productCode on the row.

  • "Find a cert by hostname or serial" → match domainName / certificateSerialNumber.

6. Domain Control Validation (DCV)

Verified against live domains. A publishable challenge is only minted after you set a method — GET /dcv is empty ({}) until then (set a method first).

Operation

Method + path

Status

Notes

Operation

Method + path

Status

Notes

Show challenge

GET /domains/{id}/dcv

Empty {} until a method is set.

Set / (re)generate method

PATCH /domains/{id}/dcv/method

🧩

Body {"dcvMethod": …}This mints the challenge token (then --show returns the _emudhra-challenge TXT record).

Trigger validation

POST /domains/{id}/dcv/verify

🧩

Empty body.

Last attempt diagnostics

GET /domains/{id}/dcv/attempts/last

Gold for debugging: MPIC per-perspective results, the CAA consensus it read, method used (e.g. CAA_EMAIL), failureClassnextSteps.

Add domain

POST /domains

🧩

Body {domainName, organizationId, dcvMethod, skipCAA}.

Deactivate domain

POST /domains/{id}/deactivate

🧩

Retire a domain.

Enum note: attempt diagnostics report methods in UPPER_SNAKE (CAA_EMAIL, …). Confirm the exact dcvMethod value the PATCH expects (DNS_TXT / HTTP_URL vs. a lowercase dns-txt) — a probable enum mismatch to watch for.

7. The approval gate (why issued ≠ done)

An accepted order sits at certificateStatus: "Pending for Approver" until approved (observed live on an ACME order). There is no REST toggle to auto-approve — per-Group Auto-Approval is set in the console by an Administrator. Until that's enabled, ACME/REST orders won't auto-issue. (Approvers also can't approve their own requests.)

8. Gaps & console-only (what REST can't do today)

  • ⛔ List a Group's permitted domains — no endpoint. GET /groups gives org bindings only; the group's Allow Domains permit-list (Domain / Permit-Deny / Scope) is console-only, and the portal's own "View Domains" can 504 on a large group.

  • ⛔ Create/edit Groupscreate ACME/EAB credentialsset per-Group Auto-Approvaledit CAA / domain permit-lists — all console + Administrator only.

  • ⚠️ GET /groups returned a subset of the groups the console shows — treat group enumeration as incomplete via REST.

9. Role matrix (Manager vs Administrator)

Capability

Manager

Needs Administrator

Capability

Manager

Needs Administrator

Auth, /auth/me

 

List/inspect orgs, domains, products

 

List/search orders (/reports/orders), ledger

 

DCV: set method / verify / diagnostics

 

Add / deactivate domains

 

Create SSL order / issue via ACME

 

Create/edit Groups, EAB accounts

 

✅ (console-only)

Per-Group Auto-Approval

 

✅ (console-only)

Edit a Group's domain permit-list

 

✅ (console-only)

10. Pagination cheat-sheet (they differ!)

Endpoint

Paging

Response

Endpoint

Paging

Response

/domains

0-based offset + limit

content[]totalElementstotalPages

/reports/orders

1-based page + size (≤100)

content[]totalElementstotalPages

/reports/ledger

1-based page + size

paged

Out-of-range page on /reports/orders is clamped to the last page (returns the last page again, not empty) — guard your loops on totalPages.