Skip to content
Jennifer Programming Language

acme API reference

An ACME (RFC 8555) client: obtain and renew TLS certificates from Let's Encrypt and compatible CAs. It drives the full flow - account registration, a new order, HTTP-01 or DNS-01 challenge, CSR finalize, and certificate download - over http + json, with every request a JWS signed by the account key (RS256 for an RSA key, ES256 for an EC key). Keys and the CSR come from the crypto library, so this needs the default jennifer binary.

The building blocks are separate calls, not one obtain(), because proving domain control is the caller's job: between order and finalize you must publish the challenge response - serve keyAuthorization at /.well-known/acme-challenge/<token> (HTTP-01), or set the dnsRecord TXT at _acme-challenge.<domain> (DNS-01) - then accept the challenge. See the demo for the orchestration.

Test against a CA's staging endpoint first (Let's Encrypt staging issues untrusted certs with far higher rate limits).

Import with import "acme.j" as acme;. See the acme guide for prose and examples.

Functions

acme.accept(client as Client, challengeUrl as string)

Tell the CA a challenge response is in place (a POST of {} to the challenge URL). Do this only after publishing the HTTP-01 / DNS-01 response.

Parameters

  • client {Client} - a registered client
  • challengeUrl {string} - the challenge URL (from challenge)

Returns {null} - nothing

Throws

  • {Error} - on an accept error

acme.authorization(client as Client, authzUrl as string)

Fetch an authorization: its domain, status, and the challenges the CA offers.

Parameters

  • client {Client} - a registered client
  • authzUrl {string} - an authorization URL (from order)

Returns {Authorization} - the authorization

acme.challenge(authz as Authorization, kind as string)

The challenge of a given type within an authorization ("http-01" / "dns-01").

Parameters

  • authz {Authorization} - an authorization from authorization
  • kind {string} - the challenge type to select

Returns {Challenge} - the matching challenge

Throws

  • {Error} - when no challenge of that type is offered

acme.connect(directoryUrl as string, accountKey as bytes)

Build a client from a CA directory URL and an account private key (PEM bytes, RSA or EC - from crypto.rsaGenerateKey / crypto.ecGenerateKey). Fetches the directory to learn the CA's endpoints. Does not yet register.

Parameters

  • directoryUrl {string} - the CA's ACME directory URL
  • accountKey {bytes} - the account private key, PEM-encoded

Returns {Client} - the configured client (kid empty until register)

Throws

  • {Error} - on a transport error or a directory missing required endpoints

acme.dnsRecord(client as Client, token as string)

The TXT record value for a DNS-01 challenge: the base64url (unpadded) SHA-256 of the key authorization. Publish it at _acme-challenge.<domain>.

Parameters

  • client {Client} - the client
  • token {string} - the challenge token

Returns {string} - the _acme-challenge TXT value

acme.downloadCertificate(client as Client, order as Order)

Download the issued certificate chain (PEM) for a valid order.

Parameters

  • client {Client} - a registered client
  • order {Order} - a valid order (with a certificate URL)

Returns {string} - the PEM certificate chain (leaf first)

Throws

  • {Error} - when the order has no certificate yet

acme.fetchOrder(client as Client, orderUrl as string)

Fetch an order's current state by URL (a POST-as-GET). Use it to poll after finalize.

Parameters

  • client {Client} - a registered client
  • orderUrl {string} - the order URL

Returns {Order} - the order's current state

acme.finalize(client as Client, order as Order, csrDer as bytes, intervalMs as int, maxTries as int)

Finalize an order by submitting a CSR, then poll the order until it is valid (the certificate is ready) or invalid. csrDer is a DER PKCS#10 request (crypto.csr(certKey, domains)) for the same domains as the order.

Parameters

  • client {Client} - a registered client
  • order {Order} - the (ready) order
  • csrDer {bytes} - the DER CSR
  • intervalMs {int} - milliseconds between status polls
  • maxTries {int} - maximum number of polls

Returns {Order} - the finalized order (certificate set when valid)

Throws

  • {Error} - on a finalize error or if issuance does not complete

acme.keyAuthorization(client as Client, token as string)

The key authorization for a challenge token: token.thumbprint, where the thumbprint is the RFC 7638 SHA-256 of the account key's JWK (base64url, unpadded). This is the exact body an HTTP-01 challenge serves at /.well-known/acme-challenge/<token>.

Parameters

  • client {Client} - the client (its account key defines the thumbprint)
  • token {string} - the challenge token

Returns {string} - the key authorization

acme.order(client as Client, domains as list of string)

Create an order for one or more domains. The returned order is pending with one authorization URL per domain.

Parameters

  • client {Client} - a registered client
  • domains {list of string} - the domains to certify (the first is the CN)

Returns {Order} - the new order

Throws

  • {Error} - on an order error

acme.pollAuthorization(client as Client, authzUrl as string, intervalMs as int, maxTries as int)

Poll an authorization until it leaves pending (becomes valid or invalid), waiting intervalMs between attempts up to maxTries.

Parameters

  • client {Client} - a registered client
  • authzUrl {string} - the authorization URL
  • intervalMs {int} - milliseconds between polls
  • maxTries {int} - maximum number of polls

Returns {Authorization} - the settled authorization

Throws

  • {Error} - if it is still pending after maxTries

acme.register(client as Client, email as string)

Register (or look up) the account with the CA and return a client carrying the account URL (kid). Agrees to the CA's terms of service. Idempotent: the CA returns the existing account for a known key.

Parameters

  • client {Client} - a client from connect
  • email {string} - a contact email (empty for none)

Returns {Client} - a client with kid set

Throws

  • {Error} - on a registration error

Structs

acme.Authorization

A domain-control authorization: the challenges the CA offers for it.

FieldTypeDescription
domainstringthe identifier being authorized
statusstringpending / valid / invalid
challengeslist of Challengethe offered challenges

acme.Challenge

One challenge within an authorization.

FieldTypeDescription
kindstringthe challenge type (http-01 / dns-01 / tls-alpn-01)
urlstringthe challenge URL (POST to it to accept / tell the CA it is ready)
tokenstringthe challenge token
statusstringpending / valid / invalid

acme.Client

An ACME client: the CA's directory endpoints plus the account key and (once registered) the account URL used as the JWS kid. Value-semantic; register returns a copy with kid filled in.

FieldTypeDescription
directorystringthe directory URL the client was built from
newNoncestringthe CA's new-nonce endpoint
newAccountstringthe CA's new-account endpoint
newOrderstringthe CA's new-order endpoint
accountKeybytesthe account private key, PEM-encoded
algstringthe JWS algorithm for the key (RS256 or ES256)
kidstringthe account URL (empty until register)

acme.Order

An ACME order for one or more identifiers (domains).

FieldTypeDescription
urlstringthe order URL (poll this for status)
statusstringpending / ready / processing / valid / invalid
authorizationslist of stringthe per-identifier authorization URLs
finalizestringthe finalize URL (POST the CSR here)
certificatestringthe certificate URL (empty until issued)