Skip to main content

Python client library for the CertiNext certificate management API

Project description

certinext

License

Python library and CLI scripts for managing your CertiNext environment via the REST API.

Contents

Requirements

  • Python 3.10+ (installed automatically when using uv — see Installation)
  • A CertiNext account with OAuth API credentials (account number + client secret)

Runtime dependencies (requests, tabulate, structlog) are installed automatically. structlog provides structured logging for the CLI tools and library internals — in cron or redirected contexts all output is emitted as JSON; in a terminal it uses a human-readable format. If you use certinext purely as a library and have a strong reason to exclude structlog, open an issue and we'll consider making it optional.

Installation

Instructions below default to uv (Install uv if you don't have it yet). You don't need Python installed first — uv downloads and manages Python for you.

To install the certinext-* CLI tools (issuing certificates, listing domains, etc.):

uv tool install "certinext[csr,keyring]"

That's the whole install — the commands now work from any terminal. (If a command isn't found, run uv tool update-shell and open a new terminal.) The two extras are recommended for CLI use: csr enables CSR parsing for certinext-issue-cert, and keyring lets the commands store and read credentials in the OS keychain.

Everything else — installing uv itself, library use, pre-releases, the UMS GitLab registry, development installs, and pip/pipx equivalents — is in the collapsible sections below.

Install uv (one-time, Windows / macOS / Linux)

Windows (PowerShell):

winget install --id=astral-sh.uv -e

macOS / Linux:

curl -LsSf https://astral.sh/uv/install.sh | sh

(On macOS, brew install uv also works.)

Then open a new terminal so uv is on your PATH. The first time a command needs Python, uv downloads a suitable version automatically.

All uv install variants (library use, pre-releases, UMS GitLab registry, development)

Library in your project — if you want import certinext in your own code, add it as a dependency of your uv-managed project:

uv add certinext

Add extras only if your code uses them: certinext[csr] (CSR parsing), certinext[keyring] (OS keychain credential lookup), certinext[dns] (DNS lookups).

Pre-releases — to get the latest alpha, beta, or release candidate:

uv tool install --prerelease=allow "certinext[csr,keyring]"   # CLI tools
uv add certinext --prerelease=allow                           # library

From the UMS GitLab package registry — releases are also published to the UMS GitLab package registry:

uv tool install certinext \
  --extra-index-url https://gitlab.its.maine.edu/api/v4/groups/2236/-/packages/pypi/simple

Development install — clone the repository, then create a venv and install in editable mode with the dev extra (test and lint toolchain plus all runtime extras):

uv venv
.venv\Scripts\activate        # Windows
# source .venv/bin/activate   # macOS / Linux

uv pip install -e ".[dev]"
Using pip or pipx instead of uv

All of the above with pip or pipx (both require Python 3.10+ already installed).

CLI tools — with pipx (isolated install, like uv tool):

pipx install "certinext[csr,keyring]"
pipx install --pip-args=--pre "certinext[csr,keyring]"   # pre-release

Or with plain pip (installs into the active Python environment, not isolated):

pip install "certinext[csr,keyring]"
pip install --pre "certinext[csr,keyring]"               # pre-release

Library in your project:

pip install certinext
pip install --pre certinext        # pre-release

Optional extras — add any of csr, keyring, or dns after the fact, e.g. the keyring extra needed by certinext-setup-keyring:

pip install "certinext[keyring]"

From the UMS GitLab package registry:

pip install certinext \
  --extra-index-url https://gitlab.its.maine.edu/api/v4/groups/2236/-/packages/pypi/simple

Development install:

python -m venv .venv
.venv\Scripts\activate        # Windows
# source .venv/bin/activate   # macOS / Linux

pip install -e ".[dev]"

Credentials

The CLI tools and Python library both talk to the CertiNext REST API, so you need REST API (OAuth) credentials — your portal username and password won't work. Generate the two required values in the CertiNext portal under Integrations → APIs → OAuth mode:

Value Description
Account number Your CertiNext account number (used as the OAuth client_id)
Client secret The OAuth access key generated in the portal
Prevetting token Optional, for auto-approving OV/EV orders — see Prevetting token

The token endpoint defaults to https://us-api.certinext.io/oauth/token. Override with --token-url if yours differs.

Storing credentials in the OS keychain (recommended)

Run the setup command once to store your credentials securely in the system keychain (Windows Credential Manager on Windows, Keychain on macOS, libsecret/SecretService on Linux):

certinext-setup-keyring

This needs the keyring extra. It's included in the recommended uv tool install "certinext[csr,keyring]" from Installation; pip users can add it with pip install "certinext[keyring]".

Scripts read credentials from the keychain automatically — no CLI flags or environment variables needed for day-to-day use.

Named profiles and credential resolution order

Named profiles

Use --profile NAME to store multiple credential sets (e.g. different accounts or environments):

certinext-setup-keyring --profile prod

Select a profile at runtime with --profile or the CERTINEXT_PROFILE environment variable:

certinext-domains --profile prod list
CERTINEXT_PROFILE=prod certinext-pending-dcv

Credential resolution order

All scripts resolve credentials in this priority order:

  1. Explicit CLI argument (--account-number, --client-secret)
  2. OS keychain (active profile; see above)
  3. Environment variables (CERTINEXT_CLIENT_ID, CERTINEXT_CLIENT_SECRET)
  4. Interactive prompt (falls back to getpass for secrets)
WSL and headless Linux (no keyring backend)

WSL and headless Linux

On Linux, keyring needs a running Secret Service daemon (gnome-keyring or KWallet). WSL and headless servers usually have none, so certinext-setup-keyring reports that no usable OS keyring backend was found. Options:

  • Skip the keyring. All scripts fall back to the CERTINEXT_CLIENT_ID and CERTINEXT_CLIENT_SECRET environment variables (see the resolution order above).

  • WSL: bridge to the Windows Credential Manager with keyring-pybridge, which forwards keyring calls to a Python interpreter on the Windows host. Credentials are then shared between Windows and WSL.

    # Prerequisite: a Windows-side Python with the keyring package installed
    pip install keyring-pybridge
    export PYTHON_KEYRING_BACKEND=keyring_pybridge.PyBridgeKeyring
    export KEYRING_PROPERTY_PYTHON='C:\path\to\python.exe'
    certinext-setup-keyring
    

    Add the two export lines to your shell profile so every session uses the bridge.

  • Headless Linux: start a Secret Service daemon such as gnome-keyring.

Prevetting token (optional, OV/EV orders)

OV and EV certificate orders normally pause at a manual approval step at the CA before issuance. If your organization has consent configured, an Organization Consent Token (prevetting token) lets the CA auto-approve the order — useful when you want certinext-issue-cert to run end-to-end without a human approving each order.

Find it in the CertiNext portal under Organization Management → Organization Consent / Consent Tokens for the target organization.

Recommended: store in the keyring once (prompted by certinext-setup-keyring):

certinext-setup-keyring   # prompts for client ID, secret, and prevetting token

certinext-issue-cert then resolves the token automatically from the keyring (or the CERTINEXT_PREVETTING_TOKEN environment variable) — no flag needed per run.

To pass it explicitly for a single run:

certinext-issue-cert example.com.csr --type ov --org-id 8921215 \
  --prevetting-token TOKEN

The token is never written to the config file by --save-defaults or certinext-setup-defaults — use the keyring or env var for persistent storage.

Storing issue-cert defaults (optional)

Store the values certinext-issue-cert needs on every run — requestor identity, certificate type, org ID, validity — so that issuing a certificate is just:

certinext-issue-cert new.csr

Run the interactive setup once:

certinext-setup-defaults

Or pass --save-defaults on any certinext-issue-cert run to capture the values you used. Or hand-edit the config file (~/.config/certinext/config.toml on Linux/macOS, %APPDATA%\certinext\config.toml on Windows, override with CERTINEXT_CONFIG):

[defaults]
requestor_name  = "Jane Doe"       # required — cannot be read from a CSR
requestor_email = "jane@maine.edu" # optional if your CSR includes an emailAddress field
requestor_phone = "+12075551234"   # required — cannot be read from a CSR (E.164 format)
# requestor_designation = "Sys Admin"  # optional
signer_place    = "Orono, ME"      # optional if your CSR includes L and/or ST fields
type            = "ov"             # required (dv / ov / ev)
org_id          = "12345"         # required for OV and EV; omit for DV
validity        = 1                # optional; defaults to 1 year
# product       = "974"            # optional product code; omit to let the API pick

[profiles.sandbox]
# overrides applied when --sandbox / --profile sandbox is active
type    = "dv"
sandbox = true                         # target the sandbox API by default

[profiles.staging]
# point a profile at any endpoint (token_url defaults to <base_url>/oauth/token)
base_url  = "https://staging-api.certinext.io"
token_url = "https://staging-api.certinext.io/oauth/token"

The primary domain and SANs are read directly from the CSR and are not stored here. requestor_email and signer_place are also read from the CSR when present (the emailAddress, L, and ST subject fields), so you only need to set them here if your CSRs don't include those fields.

A profile can also record which endpoint it targets so you don't have to pass --sandbox (or --base-url) on every run:

  • sandbox = true — the profile defaults to the sandbox endpoints.
  • base_url / token_url — the profile defaults to an explicit endpoint.

With a stored endpoint, plain certinext-domains --profile sandbox (or CERTINEXT_PROFILE=sandbox) hits the sandbox API directly. A command-line --sandbox or --base-url still overrides the stored value for that run. Set these with certinext-setup-defaults (see below) or by hand-editing.

CERTInext runs several regions. Non-US customers can point a profile at theirs — for example India production:

[profiles.india]
base_url  = "https://api.certinext.io"
token_url = "https://api.certinext.io/oauth/token"

The known endpoints (certinext.KNOWN_API_ENDPOINTS, from the OpenAPI servers list) are: US production https://us-api.certinext.io, US sandbox https://sandbox-us-api.certinext.io, India production https://api.certinext.io, plus qa-api and demo-api. certinext-setup-defaults offers these as a menu.

Values resolve in priority order: explicit CLI argument → environment variable → [profiles.NAME][defaults] → built-in default. Secrets (client secret, prevetting token) are never stored here — use certinext-setup-keyring for credentials.

Sandbox environment

A sandbox environment is available at https://sandbox-us-api.certinext.io for testing API calls without affecting production data. Store sandbox credentials once with:

certinext-setup-keyring --sandbox

Then pass --sandbox to any CLI command to target the sandbox:

certinext-accounts --sandbox
certinext-domains --sandbox list
certinext-ledger --sandbox
certinext-list-certificates --sandbox
certinext-pending-dcv --sandbox
certinext-domain-cert-count --sandbox

--sandbox is a shortcut that sets --base-url and --token-url to the sandbox endpoints and defaults --profile to sandbox.

To avoid passing --sandbox every time, record it on a profile so the profile targets the sandbox by default:

certinext-setup-defaults --profile srv-acct --sandbox   # stores sandbox = true
certinext-domains --profile srv-acct list               # hits the sandbox API

See Storing issue-cert defaults for the per-profile sandbox / base_url settings.

Integration tests

The test suite includes integration tests that call the live sandbox API. They are skipped automatically when credentials are not available, so they are safe to include in CI environments that lack a keyring.

Local development — store credentials in the keyring once:

certinext-setup-keyring --sandbox
pytest -m integration

GitLab CI — set two CI/CD Variables in the project's Settings → CI/CD → Variables:

Variable Description
CERTINEXT_SANDBOX_CLIENT_ID Sandbox account number (client ID)
CERTINEXT_SANDBOX_CLIENT_SECRET Sandbox client secret

The pipeline includes a dedicated integration-test job that runs pytest -m integration automatically whenever these variables are defined.


Using the CLI tools

The complete copy-paste path from nothing to an issued certificate (Installation covers the install command and uv itself; Credentials covers where the two credential values come from):

uv tool install "certinext[csr,keyring]"
certinext-setup-keyring      # store API credentials in the OS keychain (once)
certinext-setup-defaults     # store requestor/cert defaults (once, optional)
certinext-issue-cert example.com.csr --cert-out cert.pem --fullchain-out fullchain.pem

Each command is documented below.

certinext-setup-keyring

certinext-setup-keyring stores CertiNext API credentials in the OS keychain interactively. Run it once before using the other commands.

# Store credentials for the default profile
certinext-setup-keyring

# Store credentials for a named profile
certinext-setup-keyring --profile prod

# Store credentials for the sandbox environment
certinext-setup-keyring --sandbox

The script prompts for your account number, client secret, and (optionally) your Organization Consent Token (prevetting token for OV/EV orders). It shows any currently stored value as a default so you can keep it by pressing Enter, and masks secrets with asterisks on confirmation.

This command stores only credentials, not a URL--sandbox here is just a shortcut for --profile sandbox. If you pass both --sandbox and an explicit --profile NAME, the --sandbox flag is ignored (the profile wins) and the script warns you. To make a profile use the sandbox endpoint, set that on the profile with certinext-setup-defaults --profile NAME --sandbox.

certinext-setup-defaults

certinext-setup-defaults interactively stores defaults for certinext-issue-cert in the config file, so future issuance runs only need the CSR.

If API credentials are not yet stored, the script offers to run certinext-setup-keyring first — credentials are needed for the org picker described below.

API endpoint first. The script begins by asking which endpoint this profile should target, because the organization lookup below talks to that environment. It shows a numbered menu of the known CERTInext endpoints plus a custom-URL option:

Which CERTInext API endpoint should this profile use?
  1. Production - US (default)  https://us-api.certinext.io  [current]
  2. Sandbox - US               https://sandbox-us-api.certinext.io
  3. Production - India         https://api.certinext.io
  4. QA                         https://qa-api.certinext.io
  5. Demo                       https://demo-api.certinext.io
  6. Custom URL…

The choice is stored on the profile (sandbox = true for the US sandbox, or base_url / token_url for a region or custom host, with the token URL derived as <base_url>/oauth/token), so later runs don't need --sandbox or --base-url. Passing --sandbox or --base-url on the command line persists that choice directly and skips the menu. The endpoint list comes from certinext.KNOWN_API_ENDPOINTS.

Then the certificate defaults. It asks for certificate type (DV / OV / EV), then prompts for each field, labelling it [required] or [optional] based on the type you chose. Fields the tool can already read from a CSR (requestor_email, signer_place) are labelled optional with a note — you only need to set them here if your CSRs don't include the corresponding subject fields (emailAddress, L, ST). The domain and SANs are never prompted — they always come from the CSR.

If credentials are available, it then offers a product menu fetched from the Catalog API, filtered to the type you chose and sorted with wildcard products last. Pick one to store as the profile's default product code (sent as X-Product-Code at issue time), or choose API default to let the server pick. certinext-issue-cert --product CODE overrides the stored default per run.

For OV and EV orders, if API credentials are available the script fetches your organizations and presents them as a numbered menu filtered to pre-vetted orgs, showing validation scope and status for each (e.g. #2517111, Orono, ME, OV, Validated). A hint links to the portal (us.certinext.io or sandbox-us.certinext.io) where the default org is marked with a D badge. Falls back to free-text entry when credentials are unavailable. The organization is asked before the signer place, so when you pick one its location (City, ST) is offered as the signer-place default.

See Storing issue-cert defaults for the file format and resolution order.

# Edit the [defaults] section
certinext-setup-defaults

# Edit a profile section ([profiles.prod])
certinext-setup-defaults --profile prod

# Edit the sandbox profile (and store sandbox = true on it)
certinext-setup-defaults --sandbox

# Make a named profile target the sandbox endpoint by default
certinext-setup-defaults --profile srv-acct --sandbox

Each prompt shows the currently stored value — press Enter to keep it, or enter - to clear it.

certinext-accounts

certinext-accounts shows the current account identity, billing groups, and pre-vetted organizations.

certinext-accounts
certinext-accounts --sandbox
certinext-accounts --json
Argument Description
--json Output raw JSON instead of tabular format

certinext-domains

certinext-domains is a command-line interface for the domains API.

Common arguments

These appear before the subcommand. Credentials are optional when stored in the keychain (see Credentials above).

--profile NAME          Credential profile for keyring lookup (env: CERTINEXT_PROFILE)
--sandbox               Use the sandbox API and sandbox keyring profile
--account-number ACCT   CertiNext account number / client_id (env: CERTINEXT_CLIENT_ID)
--client-secret SECRET  OAuth2 client secret (env: CERTINEXT_CLIENT_SECRET)
--base-url URL          API base URL (default: https://us-api.certinext.io)
--token-url URL         Token endpoint URL (default: https://us-api.certinext.io/oauth/token)
--scope SCOPE           OAuth2 scope (optional)
--json                  Output raw JSON instead of tabular format
Subcommands

list

List all domains.

# credentials from keychain
certinext-domains list
certinext-domains list --offset 50 --limit 25

# credentials explicit
certinext-domains --account-number ACCT --client-secret SECRET list

get

Get a single domain by name or ID.

certinext-domains get maine.edu
certinext-domains get vuxwZgEXWWFXQQWC-...

create

Create a new domain. Additional API fields can be passed as KEY=VALUE pairs.

certinext-domains create newdomain.example.com

deactivate

Deactivate a domain by ID. Prompts for confirmation unless -y is passed.

certinext-domains deactivate DOMAIN_ID
certinext-domains deactivate DOMAIN_ID -y

get-dcv

Show current DCV status for a domain.

certinext-domains get-dcv DOMAIN_ID

verify-dcv

Trigger DCV verification for a domain.

certinext-domains verify-dcv DOMAIN_ID

change-dcv-method

Change the DCV method for a domain. Accepted values: DNS-TXT, HTTP-URL.

certinext-domains change-dcv-method DOMAIN_ID DNS-TXT

last-dcv-attempt

Show the most recent DCV attempt for a domain.

certinext-domains last-dcv-attempt DOMAIN_ID

dcv-attempt-history

Show the full DCV attempt history for a domain.

certinext-domains dcv-attempt-history DOMAIN_ID

JSON output

Add --json before the subcommand to get raw JSON instead of the default tabular output. Useful for piping into jq:

certinext-domains --json list | jq '.[] | .domainName'

certinext-ledger

certinext-ledger shows the account transaction history (all debits, credits, and running balance) with automatic pagination.

Arguments

--last N   Show only the N most recent transactions
--json     Output raw JSON instead of tabular format

Examples

certinext-ledger
certinext-ledger --last 20
certinext-ledger --sandbox --json

certinext-list-certificates

certinext-list-certificates lists all SSL/TLS certificate orders from the orders report. Use --status to filter by lifecycle status.

Arguments

--status STATUS   Filter by certificate status (issued, expired, pending-dcv, etc.)
--json            Output raw JSON instead of tabular format

Examples

certinext-list-certificates
certinext-list-certificates --status issued
certinext-list-certificates --status expired
certinext-list-certificates --status pending-dcv
certinext-list-certificates --sandbox --json

certinext-pending-dcv

certinext-pending-dcv lists every active domain that has not yet completed DCV verification. It is a quick read-only diagnostic — no changes are made to any domain.

Arguments

--profile NAME          Credential profile for keyring lookup (env: CERTINEXT_PROFILE)
--sandbox               Use the sandbox API and sandbox keyring profile
--account-number ACCT   CertiNext account number (env: CERTINEXT_CLIENT_ID)
--client-secret SECRET  OAuth2 client secret (env: CERTINEXT_CLIENT_SECRET)
--base-url URL          API base URL (default: https://us-api.certinext.io)
--token-url URL         Token endpoint URL (default: https://us-api.certinext.io/oauth/token)
--pattern REGEX         Filter by domain name regex (re.fullmatch, case-insensitive)
--json                  Output raw JSON instead of tabular format

Examples

# Credentials from keychain (no flags needed after setup)
certinext-pending-dcv

# Use a named profile
certinext-pending-dcv --profile prod

# Filter to a specific subdomain pattern
certinext-pending-dcv --pattern ".*\.maine\.edu"

# Raw JSON output for scripting
certinext-pending-dcv --json | jq '.[] | .domainName'

# Credentials from environment variables
CERTINEXT_CLIENT_ID=ACCT CERTINEXT_CLIENT_SECRET=SECRET certinext-pending-dcv

certinext-domain-cert-count

certinext-domain-cert-count shows all registered domains and how many certificates each one has. It fetches the domain list and the orders report, then matches each certificate to its most specific registered domain by suffix — a cert for host.subdomain.example.org counts toward subdomain.example.org when that domain is registered, rather than the less-specific example.org.

Arguments

--profile NAME           Credential profile for keyring lookup (env: CERTINEXT_PROFILE)
--sandbox                Use the sandbox API and sandbox keyring profile
--account-number ACCT    CertiNext account number (env: CERTINEXT_CLIENT_ID)
--client-secret SECRET   OAuth2 client secret (env: CERTINEXT_CLIENT_SECRET)
--base-url URL           API base URL (default: https://us-api.certinext.io)
--token-url URL          Token endpoint URL (default: https://us-api.certinext.io/oauth/token)
--status issued|expired  Filter to only issued or only expired certificates
--condense               Show only top-level domains; subdomain counts roll up into their apex
--json                   Output raw JSON instead of tabular format

Examples

# All certificates, all statuses (credentials from keychain)
certinext-domain-cert-count

# Only issued (active) certificates
certinext-domain-cert-count --status issued

# Only expired certificates
certinext-domain-cert-count --status expired

# Collapse subdomains — subdomain.example.org rolls into example.org
certinext-domain-cert-count --condense

# Condense + issued only
certinext-domain-cert-count --condense --status issued

# Raw JSON for scripting
certinext-domain-cert-count --json | jq '.[] | select(.certificates != "0")'

certinext-issue-cert

certinext-issue-cert submits a CSR to CertiNext and downloads the issued certificate. It reads the domain and SANs directly from the CSR, creates a certificate order, handles the full lifecycle (agreement, DCV if needed, CSR submission), and writes the signed PEM to stdout or a file once the CA has issued it.

Requires the csr optional extra — included in the recommended uv tool install "certinext[csr,keyring]" from Installation.

Arguments

# Connection
--profile NAME              Credential profile for keyring lookup (env: CERTINEXT_PROFILE)
--sandbox                   Use the sandbox API and sandbox keyring profile
--account-number ACCT       CertiNext account number (env: CERTINEXT_CLIENT_ID)
--client-secret SECRET      OAuth2 client secret (env: CERTINEXT_CLIENT_SECRET)

# Certificate
csr_file                    PEM-encoded CSR file (positional; omit to read from stdin)
--csr FILE                  Same as positional argument
--type dv|ov|ev             Validation type (default: dv)
--validity YEARS            Validity in years: 1, 2, or 3 (default: 1)
--org-id ID                 Organization ID — required for OV and EV certificates
--product CODE              Product code (X-Product-Code) selecting a specific
                            catalog product; default: API default for the type.
                            List codes with certinext-setup-defaults.
--domain FQDN               Override the primary domain (default: extracted from CSR CN)
--san FQDN                  Override SANs (default: extracted from CSR; repeatable)
--auto-secure-www           Request automatic www-redirect coverage (API default: true)

# Requestor (can also be set via environment variables)
--requestor-name NAME       Full name of the requestor (env: CERTINEXT_REQUESTOR_NAME)
--requestor-email EMAIL     Email address of the requestor (env: CERTINEXT_REQUESTOR_EMAIL)
--requestor-phone PHONE     Phone in E.164 format, e.g. +12075551234 (env: CERTINEXT_REQUESTOR_PHONE)
--requestor-designation TTL Job title or designation (env: CERTINEXT_REQUESTOR_DESIGNATION)
--signer-place PLACE        City/location for the subscriber agreement (env: CERTINEXT_SIGNER_PLACE)

# Output / control
-o FILE, --output FILE      Write the certificate PEM bundle to FILE (default: stdout)
--cert-out FILE             Write only the end-entity (leaf) certificate PEM to FILE
--chain-out FILE            Write only the intermediate CA chain PEM to FILE (signing order)
--fullchain-out FILE        Write the leaf-first fullchain PEM (leaf + intermediates) to FILE
--der-out FILE              Write the end-entity certificate in DER (binary) format to FILE
--all-formats-out DIR       Write {domain}.pem and {domain}.der to DIR in one call
--raw-chain                 Emit the chain exactly as the API returns it, unsorted
                            (default: sort into leaf-first signing order; see below)
--wait SECONDS              Seconds to wait for issuance (default: 300; 0 = submit and exit)
--order-id ID               Resume polling an existing order instead of creating a new one
--save-defaults             Store the effective requestor/certificate values as config defaults
-v, --verbose               Increase verbosity (-vvv for debug logging)

Requestor and certificate values can also come from stored defaults — see Storing issue-cert defaults.

Examples

# DV certificate — credentials and requestor info from keychain / env vars
certinext-issue-cert example.com.csr

# Read CSR from stdin
certinext-issue-cert < example.com.csr

# Save certificate to a file
certinext-issue-cert example.com.csr --output example.com.pem

# Write leaf, intermediate chain, and fullchain to separate files
# (the layout nginx, Apache, and HAProxy configs typically expect)
certinext-issue-cert example.com.csr --cert-out cert.pem --chain-out chain.pem --fullchain-out fullchain.pem

# Emit the chain exactly as the API returns it, without re-sorting (debugging)
certinext-issue-cert example.com.csr --fullchain-out fullchain.pem --raw-chain

# OV certificate with explicit org
certinext-issue-cert example.com.csr --type ov --org-id 8921215

# Two-year DV certificate against the sandbox
certinext-issue-cert example.com.csr --validity 2 --sandbox

# Submit and exit immediately without waiting for issuance
certinext-issue-cert example.com.csr --wait 0

# Resume polling an order created in a previous run
certinext-issue-cert --order-id ORDER-ID --wait 600

# Resume and supply the CSR (in case the order is still in pending-csr)
certinext-issue-cert --order-id ORDER-ID --csr example.com.csr

# Capture the values used on this run as defaults for future runs
certinext-issue-cert example.com.csr --type ov --org-id 8921215 --save-defaults

To avoid repeating requestor flags on every call, store them once with certinext-setup-defaults (or --save-defaults above), or set environment variables (which take precedence over stored defaults):

export CERTINEXT_REQUESTOR_NAME="Jane Doe"
export CERTINEXT_REQUESTOR_EMAIL="jane.doe@example.com"
export CERTINEXT_REQUESTOR_PHONE="+12075551234"
export CERTINEXT_REQUESTOR_DESIGNATION="Systems Administrator"
export CERTINEXT_SIGNER_PLACE="Portland, ME"

certinext-issue-cert example.com.csr --output example.com.pem

Certificate lifecycle

The tool handles the full CertiNext order lifecycle automatically:

  1. pending-approval — waits for CA approval (no action needed)
  2. pending-agreement — accepts the subscriber agreement on your behalf
  3. pending-dcv — logs challenge details and triggers verification; in environments where domains are pre-validated (e.g. University of Maine System), DCV auto-resolves without manual intervention
  4. pending-csr — submits the provided CSR
  5. issued — downloads and writes the PEM certificate chain

If the order does not reach issued within --wait seconds, the tool exits with code 1 and prints the order ID so you can resume with --order-id.

certinext-parent-dcv-status

certinext-parent-dcv-status shows DCV status and expiry for every domain that requires direct DCV validation — either because it has no registered ancestor in the account, or because its own NS records form a DNS zone boundary that blocks DCV inheritance from a parent.

By default an NS lookup is performed for each domain to detect zone boundaries (requires certinext[dns]). Use --no-ns-check to skip DNS lookups and list only account-level parents.

Arguments

--pattern REGEX         Filter domains by regex before identifying parents (re.fullmatch)
--status STATUS         Filter by DCV status: all (default), verified, expiring, pending, expired
--expiring-days DAYS    Days ahead to flag as expiring soon (default: 30)
--json                  Output raw JSON instead of tabular format
--no-ns-check           Skip DNS NS lookups; list account-level parents only
-v, --verbose           Increase verbosity (-v shows progress, -vvv enables debug logging)

Examples

# All parent domains with DCV status
certinext-parent-dcv-status --sandbox

# Only domains expiring within 60 days
certinext-parent-dcv-status --status expiring --expiring-days 60

# Skip DNS NS checks (faster, account-level parents only)
certinext-parent-dcv-status --no-ns-check

# Raw JSON for scripting
certinext-parent-dcv-status --json | jq '.[] | select(.dcv_status != "VERIFIED")'

certinext-healthcheck

certinext-healthcheck probes (nearly) every read-only CertiNext endpoint the library exposes, classifies each result, and prints a scannable report of what works for the credentials it was given. It is read-only and safe to run against production — it only ever issues GETs and never mutates anything.

Use it to answer two questions the CertiNext API makes surprisingly hard:

  • "What should work with our library right now, against this account?" — the vendor changes behaviour that affects some orgs and environments but not others, and drifts over time.
  • (future, with fine-grained API keys) "Does this key have exactly the access it should?" — a DENIED outcome is the permission-denied signal.

Probes run in two tiers. Tier 1 needs no input and always runs. Tier 2 needs an ID derived from a Tier-1 result (a specific organization, product, domain, or order); when that input is unavailable the probe is reported SKIPPED, never as a failure. Use --quick to run Tier 1 only.

Outcomes

Outcome Meaning Fails the run?
PASS 2xx with data (or a legitimately empty result) no
EMPTY 2xx but unexpectedly empty where a baseline says it shouldn't be only with --strict
DENIED 401/403, or a token error naming invalid_client yes
NOT_FOUND 404 yes
SERVER_BUG 422 or 5xx — the raw RFC 7807 body is captured verbatim yes
RATE_LIMITED 429 no
NETWORK connection/timeout error with no HTTP response yes
SKIPPED a Tier-2 probe whose derived input was unavailable no

The process exits non-zero when any probe is DENIED, NOT_FOUND, SERVER_BUG, or NETWORK. Add --strict to also fail on EMPTY.

Case study: the June 2026 /domains 422 (resolved)

In mid-June 2026 the CertiNext /domains list endpoint returned a generic HTTP 422 for every request made with our production credentials (CertiNext ticket #131869). The root cause turned out to be on the account side — a credentials/provisioning problem, resolved 2026-06-25 by issuing new OAuth client credentials — not a fault in this library.

While it lasted, certinext-healthcheck reported the domain-list probe as SERVER_BUG (with the raw RFC 7807 body captured verbatim) and the per-domain Tier-2 probes that depend on a domain from that list as SKIPPED, so the run exited non-zero. That is exactly the behaviour the tool exists for: it pinpointed the broken endpoint and preserved the server's own error body, instead of letting the failure surface as a confusing crash downstream. As of 2026-07-02 both production and sandbox runs are fully green.

Arguments

--quick                 Run Tier-1 probes only (skip derived-input Tier-2 probes)
--strict                Also exit non-zero on an unexpectedly empty baseline list (EMPTY)
--json                  Write the full results (with raw error bodies) as JSON
-v, --verbose           Increase verbosity (-v progress, -vvv per-probe debug)

Examples

# Probe the sandbox and show progress
certinext-healthcheck --sandbox -v

# Probe production (read-only) — surfaces any endpoint that is down for this account
certinext-healthcheck

# Tier-1 only, for a fast auth/connectivity canary
certinext-healthcheck --quick

# Machine-readable output, with the raw RFC 7807 body for any 422
certinext-healthcheck --json | python -m json.tool

# Nightly cron that alerts on regressions via the exit code
certinext-healthcheck 2>> /var/log/certinext-health.log || mail -s "CertiNext health" ops@example.edu

Log output

All CLI scripts write diagnostic messages to stderr. The format adapts to the environment automatically:

Context Format
Interactive terminal (TTY) HH:MM:SS [level] event field=value … — human-readable, local time
Non-TTY (cron, redirected stderr) One JSON object per line — suitable for log aggregators and jq

Verbosity flags (cumulative, same for all scripts):

Flag Effect
-v Show extra context fields (correlation_id, pid, credential profile, domain filters)
-vvv Enable DEBUG logging
-vvvv Also enable third-party DEBUG output (urllib3, keyring)

Cron example — capture JSON logs to a file:

certinext-parent-dcv-status --sandbox 2>> /var/log/certinext.log

Each line is a self-contained JSON object:

{"timestamp": "2026-06-03T14:00:01.234Z", "level": "info", "event": "Connecting", "account": "5912517854", "profile": "default", "url": "https://us-api.certinext.io"}
{"timestamp": "2026-06-03T14:00:02.456Z", "level": "info", "event": "Fetched domains", "count": 234}

Python library

Creating a session

import certinext

sess = certinext.session(
    client_id="YOUR_ACCOUNT_NUMBER",
    client_secret="YOUR_CLIENT_SECRET",
)
All session() parameters
sess = certinext.session(
    client_id="YOUR_ACCOUNT_NUMBER",
    client_secret="YOUR_CLIENT_SECRET",
    scope="",           # optional
    sandbox=False,      # True → use sandbox endpoints automatically
    base_url="",        # override; defaults to production (or sandbox when sandbox=True)
    token_url="",       # override; defaults to match base_url
)

When sandbox=True, base_url and token_url default to the sandbox endpoints (https://sandbox-us-api.certinext.io). Explicit base_url / token_url values always take precedence over the sandbox flag.

The session obtains and caches an OAuth 2.0 bearer token automatically, refreshing it before it expires.

Working with domains

List all domains

domains = sess.domain.get_list()
for d in domains:
    print(d)

With no offset/limit, get_list() returns the complete account, paging under an explicit sortBy=domainName sort behind the scenes — that sort is a stable total order regardless of account size.

Pass offset and limit explicitly to fetch a single raw server page instead, under whichever ordering the API applies by default:

page = sess.domain.get_list(offset=50, limit=25)

Note: the API's default sort order for a raw page like this is not a stable total order across offset values — rows can be skipped or duplicated between pages if you loop offset yourself. Omit offset/limit for a reliable full list instead.

Filter by status server-side (reduces data transferred):

# Only active domains with pending or rejected DCV
domains = sess.domain.get_list(domain_status="ACTIVE", dcv_status="PENDING,REJECTED,EXPIRED")

Note: The API search parameter behaves differently per environment (re-tested 2026-07-02, probe R01): exact FQDN matches work everywhere; the sandbox now also matches substrings correctly, but production still returns 0 results for substring searches — and results are capped at the server's ~50-row default page. Use pattern (below) for reliable filtering.

Filter by name with a regex (applied client-side after the API response):

# Exact match
domains = sess.domain.get_list(pattern=r"maine\.edu")

# Multiple names via alternation
domains = sess.domain.get_list(pattern=r"maine\.edu|umaine\.edu")

# Subdomain wildcard
domains = sess.domain.get_list(pattern=r".*\.maine\.edu")

pattern uses re.fullmatch with re.IGNORECASE, so it must match the entire domain name. Combine with status filters to narrow the API response first:

domains = sess.domain.get_list(domain_status="ACTIVE", pattern=r".*\.maine\.edu")

List domains needing DCV

get_pending_dcv() returns active domains that have not yet completed DCV verification. It fetches all domains and filters client-side using domain.needs_dcv.

Note: Combining the API domainStatus and dcvStatus filter parameters originally returned a 400 error (reported 2026-05-20), so this method fetches all domains and filters client-side. Probe R02 confirmed the combination now works in both environments (2026-07-02, GitLab issue #6); the switch to server-side filtering is planned for the 1.0 refactor.

pending = sess.domain.get_pending_dcv()

# Narrow to a subset by name
pending = sess.domain.get_pending_dcv(pattern=r".*\.maine\.edu")

Get a domain

Look up by domain name or by domain ID:

domain = sess.domain.get("maine.edu")
domain = sess.domain.get("vuxwZgEXWWFXQQWC-3zElI5VlhinKlE8xyYJqfeYNtFE0SAP")

When a name is passed (contains a .), the library lists all domains and finds the match. When an ID is passed, it calls the single-domain endpoint directly.

Create a domain

domain = sess.domain.create("newdomain.example.com")
Domain properties and DcvInfo fields

Domain properties

Property Type Description
id str | None Domain ID
name str | None Domain name (FQDN). Settable, but only updates the local object — does not persist to the API.
status str | None ACTIVE or INACTIVE
dcv_status str | None VERIFIED, PENDING, REJECTED, EXPIRED, etc.
organization_id str | None Organization ID
organization_name str | None Organization display name
created_at datetime | None Creation timestamp (timezone-aware UTC)
needs_dcv bool True if status is ACTIVE and dcv_status is not VERIFIED

Domain objects support str() and repr():

print(domain)
# Domain: maine.edu
#   id:              vuxwZgEXWWFXQQWC-...
#   status:          ACTIVE
#   dcv_status:      VERIFIED
#   organization:    University of Maine System
#   created:         2026-05-04 21:27:14+00:00

repr(domain)
# Domain(id='vuxwZgEXWWFXQQWC-...', name='maine.edu', status='ACTIVE', dcv_status='VERIFIED')

DcvInfo

domain.get_dcv() returns a DcvInfo dataclass with the following fields:

Field Type Description
method str DCV method in upper case: DNS-TXT or HTTP-URL
token str Challenge value to publish (TXT record content for DNS-TXT, file token for HTTP-URL)
host str Sub-domain prefix for the challenge record (e.g. _emudhra-challenge). Empty string if not returned by the API.

Domain methods

# Re-fetch from API and update the object in place
domain.refresh()

# Deactivate (updates the object in place, returns self)
domain.deactivate()

# DCV — Domain Control Validation
dcv = domain.get_dcv()             # returns DcvInfo(method, token, host)
print(dcv.method)                  # e.g. "DNS-TXT" or "HTTP-URL"
print(dcv.token)                   # challenge value to publish
print(dcv.host)                    # sub-domain prefix for the challenge record

result = domain.verify()           # trigger verification; returns raw API response dict
domain.change_dcv_method("DNS-TXT")   # accepted values: "DNS-TXT", "HTTP-URL"
attempt = domain.last_dcv_attempt()   # returns raw API response dict
history = domain.dcv_attempt_history() # returns raw API response dict or list

# Get the raw API response dict
raw = domain.as_dict()

Example: verify all pending domains

import certinext

sess = certinext.session(
    client_id="YOUR_ACCOUNT_NUMBER",
    client_secret="YOUR_CLIENT_SECRET",
)

# Due to a vendor API bug, server-side status filtering is currently disabled.
# get_pending_dcv() fetches all domains and filters client-side for needs_dcv.
for domain in sess.domain.get_pending_dcv():
    print(f"Verifying {domain.name} ...")
    domain.verify()

Or check needs_dcv manually if you already have a full domain list:

for domain in sess.domain.get_list():
    if domain.needs_dcv:
        print(f"Verifying {domain.name} ...")
        domain.verify()

Working with orders

sess.orders provides access to the CertiNext orders report API (GET /api/certinext/v2/reports/orders).

Fetch all orders

orders = sess.orders.get_list()
for o in orders:
    print(o.common_name, o.certificate_status)

Filter by certificate status:

issued = sess.orders.get_list(status="issued")
expired = sess.orders.get_list(status="expired")

get_list() paginates automatically. Use get_page() for manual control:

page = sess.orders.get_page(page=1, size=50, status="issued")

OrderRecord properties

Property Type Description
order_number str | None CertiNext order number
request_number str | None Request number
product_code str | None Product code (e.g. OV_SSL, DV_SSL)
order_status str | None Order lifecycle status (e.g. complete)
certificate_status str | None Certificate status (issued, expired, etc.)
common_name str | None Certificate common name (hostname or domain)
o.as_dict()   # raw API response dict
o.to_row()    # flat dict[str, str] for tabular display
repr(o)       # OrderRecord(order_number='ORD-001', common_name='example.org', ...)

Working with accounts

sess.accounts exposes the authenticated account identity, billing groups, and pre-vetted organizations.

me = sess.accounts.me()
print(me.account_number, me.account_name, me.account_type)

groups = sess.accounts.list_groups()
for g in groups:
    print(g.group_number, g.group_name)

orgs = sess.accounts.list_organizations()
for o in orgs:
    print(o.organization_number, o.organization_name, o.locality)

# Fetch a single organization by its number
org = sess.accounts.get_organization("8921215")

Working with the catalog

sess.catalog lists available certificate products and their custom fields.

categories = sess.catalog.list_products()
for cat in categories:
    for product in cat.products:
        print(product.product_code, product.product_name, product.price)

# Custom fields required for a specific product
fields = sess.catalog.get_custom_fields("842")
for f in fields:
    print(f.field_name, f.required)

Working with the ledger

sess.ledger provides access to the account transaction history.

records = sess.ledger.get_list()
for r in records:
    print(r.transaction_date, r.description, r.debit, r.credit, r.balance)

# Single page
page = sess.ledger.get_page(page=1, size=50)

get_list() paginates automatically. LedgerRecord.to_row() returns a flat dict[str, str] suitable for tabulate.

Working with SSL/TLS certificates

sess.ssl covers the full certificate lifecycle. Product codes are resolved automatically from the catalog — you never hardcode a product code.

Create a certificate

Use sess.ssl.create() when the validation level is a runtime value (e.g. read from configuration). It dispatches to the appropriate create_* method and validates that organization_id is provided for OV and EV orders:

# Product determined at runtime (e.g. from config)
order = sess.ssl.create("dv", "example.com", validity_years=1)
order = sess.ssl.create("ov", "example.com", organization_id="8921215", validity_years=1)
order = sess.ssl.create("ev", "example.com", organization_id="8921215", validity_years=1)

Or call the specific variant directly:

# DV single-domain
order = sess.ssl.create_dv("example.com", validity_years=1)

# DV wildcard
order = sess.ssl.create_dv_wildcard("example.com", validity_years=1)

# OV single-domain (requires organization_id from sess.accounts.list_organizations())
order = sess.ssl.create_ov("example.com", organization_id="8921215", validity_years=1)

# EV single-domain
order = sess.ssl.create_ev("example.com", organization_id="8921215", validity_years=1)

# UCC (multi-domain) — pass a list for DV, OV, or EV
order = sess.ssl.create_dv_ucc(["example.com", "www.example.com"], validity_years=1)

DV lifecycle

Each mutation call returns an opaque response dict; call order.refresh() afterwards to see the updated order.status.

# 1. Get challenges
for challenge in order.get_dcv():
    print(challenge.domain, challenge.method, challenge.host, challenge.token)

# 2. (Publish the DNS TXT or HTTP file challenge externally)

# 3. Trigger verification (publish the challenge first, then call this)
order.verify_dcv()
order.refresh()
print(order.status)  # "pending-csr" once DCV passes

# 4. Submit CSR
order.submit_csr(csr_pem)
order.refresh()

# 5. Accept agreement
order.accept_agreement()
order.refresh()
print(order.status)  # "pending-approval" or "issued"

# 6. Download once issued
cert = order.download_certificate()           # JSON — cert + chain PEM strings
pem  = order.download_certificate_pem()      # raw PEM bundle (API order — see note below)
chain = order.download_certificate().as_pem_chain()  # leaf-first fullchain, sorted into signing order
der  = order.download_certificate_der()      # raw DER bytes

Complete end-to-end DV example:

import certinext, time

sess = certinext.session(client_id="YOUR_ACCOUNT", client_secret="YOUR_SECRET")

order = sess.ssl.create_dv("example.com", validity_years=1)
print(f"Order {order.order_id} created, status={order.status}")

for ch in order.get_dcv():
    print(f"  {ch.domain}: add TXT at {ch.host!r}  value={ch.token!r}")

input("Press Enter once DNS TXT records are published…")

order.verify_dcv()
order.submit_csr(open("csr.pem").read())
order.accept_agreement()

while True:
    order.refresh()
    if order.status == "issued":
        break
    print(f"  status={order.status}, waiting…")
    time.sleep(30)

open("cert.pem", "w").write(order.download_certificate_pem())
print("Certificate written to cert.pem")

Retrieve an existing order

order = sess.ssl.get("ORDER-ID")
print(order.status, order.domain, order.created_at)
order.refresh()   # re-fetch current state from the API

OrderWorkflow helpers

OrderWorkflow drives an order through its full lifecycle automatically. Three helpers simplify common patterns:

from certinext import OrderWorkflow

# Drive a new order to issuance (blocking)
wf = OrderWorkflow.from_csr(order, csr_pem, signer_name="Jane Doe")
pem = wf.run()   # blocks until issued or timeout

# Resume from a persisted order ID (e.g. after a restart)
wf = OrderWorkflow.from_order_id(sess, "ORDER-ID", signer_name="Jane Doe")
wf.advance(csr_pem)   # one non-blocking step

# Download the issued certificate as a deterministic leaf-first fullchain
chain = wf.download_chain()   # retries HTTP 422 ("not ready yet") automatically

download_chain() uses CertificateDownload.as_pem_chain() internally — the end-entity certificate followed by its intermediates, with a single trailing newline. Use this instead of download() when the bundle order matters (e.g. when writing a fullchain.pem for an ACME server).

Chain ordering. CertiNext returns the chain in a non-standard order — the root CA appears right after the leaf instead of last — which breaks Windows Schannel / IIS validation (GitLab #4). as_pem_chain() (and download_chain(), --fullchain-out, --chain-out, and the --output/stdout bundle) re-sort the chain into correct leaf-first signing order by default. Pass as_pem_chain(sort=False) — or certinext-issue-cert --raw-chain — to emit the exact bytes the API returned. Sorting needs the cryptography package (pip install certinext[csr]); without it the CLI exits with guidance and the library raises ImportError unless you use the raw path.

Other lifecycle operations

order.cancel()
order.revoke(reason="keyCompromise")
order.reissue("rekey", csr=new_csr_pem)

Examples

DNS-TXT DCV automation

examples/dns_txt_dcv.py is a ready-to-adapt script that automates the full DNS-TXT DCV pipeline: publishing the challenge token, waiting for DNS propagation, and triggering domain.verify() once the token is visible everywhere.

It contains two stub functions you implement for your DNS provider:

Function Purpose
set_dns_txt_record(fqdn, value, dry_run) Publish the TXT record via your DNS provider API
has_dns_txt_record(fqdn, value, nameserver) Check whether a nameserver returns the expected TXT value

Each stub raises NotImplementedError until implemented and includes inline examples using dnspython (nsupdate/TSIG) and AWS Route 53 (boto3).

Usage
export CERTINEXT_CLIENT_ID="your-account-number"
export CERTINEXT_CLIENT_SECRET="your-client-secret"

# Process all pending domains
python examples/dns_txt_dcv.py

# Preview without making changes
python examples/dns_txt_dcv.py --dry-run

# Limit to a specific domain or pattern
python examples/dns_txt_dcv.py example.com
python examples/dns_txt_dcv.py --pattern r".*\.example\.com"

# Configure nameserver propagation checks
python examples/dns_txt_dcv.py \
  --auth-nameservers ns1.example.com,ns2.example.com \
  --public-nameservers 8.8.8.8,1.1.1.1

Run the script repeatedly — each run advances every pending domain as far as it can go and exits cleanly when waiting for propagation. Once a domain is fully propagated, the script calls domain.verify() automatically.


API documentation

The CertiNext REST API is documented in two places:

Resource URL Notes
Swagger UI (sandbox) sandbox-us-api.certinext.io/swagger-ui/index.html Interactive; select certinext-v2 from the spec dropdown
OpenAPI spec (sandbox) sandbox-us-api.certinext.io/v3/api-docs/certinext-v2 Raw JSON — complete schema including undocumented fields
Postman collection documenter.getpostman.com/… Official docs; less complete than the Swagger spec

Replace sandbox-us-api.certinext.io with us-api.certinext.io for the production equivalents.

The Swagger spec is the most authoritative source — it exposes fields not present in the Postman collection (e.g. preVettingToken, csr in the initial order body, delegation, recipientEmails, tags).


Project structure

File tree
certinext/
    __init__.py                   # session() factory, top-level exports, URL constants
    _cli.py                       # shared CLI utilities (add_connection_args, add_requestor_args, fatal_api_error, build_session)
    _config.py                    # stored issue-cert defaults (config.toml load/merge/save)
    _keyring.py                   # shared keyring helpers (keyring_service, keyring_get, keyring_available, no_keyring_help)
    accounts.py                   # AccountInfo, Group, Organization, AccountAccessor
    accounts_cli.py               # certinext-accounts CLI entry point
    auth.py                       # OAuth 2.0 client credentials token management
    catalog.py                    # Product, ProductCategory, CustomField, CatalogAccessor
    client.py                     # HTTP session wrapper (get/post/put/delete/get_bytes)
    csr.py                        # parse_csr() — extract CN and SANs from a PEM CSR (requires certinext[csr])
    domain_cert_count_cli.py      # certinext-domain-cert-count CLI entry point
    domains.py                    # Domain class and DomainAccessor
    domains_cli.py                # certinext-domains CLI entry point
    exceptions.py                 # CertiNextAPIError
    issue_certificate_cli.py      # certinext-issue-cert CLI entry point
    ledger.py                     # LedgerRecord and LedgerAccessor
    ledger_cli.py                 # certinext-ledger CLI entry point
    list_certificates_cli.py      # certinext-list-certificates CLI entry point
    orders.py                     # OrderRecord and OrderAccessor
    pending_dcv_cli.py            # certinext-pending-dcv CLI entry point
    session.py                    # CertiNextSession (accounts, catalog, domain, ledger, orders, ssl)
    setup_defaults_cli.py         # certinext-setup-defaults CLI entry point
    setup_keyring_cli.py          # certinext-setup-keyring CLI entry point
    ssl_certificates.py           # SslOrder, DcvChallenge, CertificateDownload, SslAccessor, OrderWorkflow
                                  #   SslAccessor.create() — DV/OV/EV dispatcher
                                  #   CertificateDownload.as_pem_chain() — leaf-first fullchain
                                  #   OrderWorkflow.download_chain() — 422-retry + normalised chain
                                  #   OrderWorkflow.from_order_id() — resume from persisted order ID
tests/
    test_integration.py           # integration tests against the sandbox API (pytest -m integration)
examples/
    dns_txt_dcv.py                # DNS-TXT DCV automation example (see Examples above)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

certinext-0.3.0rc10.tar.gz (227.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

certinext-0.3.0rc10-py3-none-any.whl (139.9 kB view details)

Uploaded Python 3

File details

Details for the file certinext-0.3.0rc10.tar.gz.

File metadata

  • Download URL: certinext-0.3.0rc10.tar.gz
  • Upload date:
  • Size: 227.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for certinext-0.3.0rc10.tar.gz
Algorithm Hash digest
SHA256 e0c9490836adf530ea772c74c062a38bcd66b0a1ab83ef786c3f9db0721cb527
MD5 e5de571933274e61bba8ab602eb19763
BLAKE2b-256 36cdfff8f0e553aba1e74bcaee7f9c35d463e1c0a587f16183661c24f2ff47e6

See more details on using hashes here.

Provenance

The following attestation bundles were made for certinext-0.3.0rc10.tar.gz:

Publisher: ci.yml on tod-uma/certinext

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file certinext-0.3.0rc10-py3-none-any.whl.

File metadata

  • Download URL: certinext-0.3.0rc10-py3-none-any.whl
  • Upload date:
  • Size: 139.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for certinext-0.3.0rc10-py3-none-any.whl
Algorithm Hash digest
SHA256 6ee66df7f2ac667eb684a3c4b6d6143c81c3a717ba40d29b3a2253cec7490eb0
MD5 228680b73944949571ebe7f488337f77
BLAKE2b-256 249bd8c4de153f51de10e1831b3cea843d1f9e54a314c34ea5374b88808e60f3

See more details on using hashes here.

Provenance

The following attestation bundles were made for certinext-0.3.0rc10-py3-none-any.whl:

Publisher: ci.yml on tod-uma/certinext

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page