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 clientchallengeUrl{string}- the challenge URL (fromchallenge)
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 clientauthzUrl{string}- an authorization URL (fromorder)
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 fromauthorizationkind{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 URLaccountKey{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 clienttoken{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 clientorder{Order}- avalidorder (with acertificateURL)
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 clientorderUrl{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 clientorder{Order}- the (ready) ordercsrDer{bytes}- the DER CSRintervalMs{int}- milliseconds between status pollsmaxTries{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 clientdomains{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 clientauthzUrl{string}- the authorization URLintervalMs{int}- milliseconds between pollsmaxTries{int}- maximum number of polls
Returns {Authorization} - the settled authorization
Throws
{Error}- if it is still pending aftermaxTries
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 fromconnectemail{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.
| Field | Type | Description |
|---|---|---|
domain | string | the identifier being authorized |
status | string | pending / valid / invalid |
challenges | list of Challenge | the offered challenges |
acme.Challenge
One challenge within an authorization.
| Field | Type | Description |
|---|---|---|
kind | string | the challenge type (http-01 / dns-01 / tls-alpn-01) |
url | string | the challenge URL (POST to it to accept / tell the CA it is ready) |
token | string | the challenge token |
status | string | pending / 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.
| Field | Type | Description |
|---|---|---|
directory | string | the directory URL the client was built from |
newNonce | string | the CA's new-nonce endpoint |
newAccount | string | the CA's new-account endpoint |
newOrder | string | the CA's new-order endpoint |
accountKey | bytes | the account private key, PEM-encoded |
alg | string | the JWS algorithm for the key (RS256 or ES256) |
kid | string | the account URL (empty until register) |
acme.Order
An ACME order for one or more identifiers (domains).
| Field | Type | Description |
|---|---|---|
url | string | the order URL (poll this for status) |
status | string | pending / ready / processing / valid / invalid |
authorizations | list of string | the per-identifier authorization URLs |
finalize | string | the finalize URL (POST the CSR here) |
certificate | string | the certificate URL (empty until issued) |