ACME Status

GET /v1/domains/self/{uuid}/acme/status

Current state of a custom domain and its automated TLS certificate issuance. The platform issues certificates via Let's Encrypt (or another configured ACME CA) using the DNS-01 challenge against the provider you configured. This endpoint reports the domain's status, the last issuance error and time, and the most recent ACME job.

Useful for surfacing TLS health to users and for integrations that need to wait for a fresh cert before deploying — poll it while status is pending_issuance or issuing. Renewal happens automatically before the certificate expires — to force an immediate reissue, use POST /v1/domains/self/{uuid}/reissue-ssl.

It is also the endpoint to poll after Check again on a domain suspended because its registration expired: while suspended, the response carries an expiry_suspension object.

The registration object reports the domain's registration (at the registrar — not the TLS certificate): its expiry date, where the platform read it (Cloudflare Registrar, RDAP or WHOIS), the registry's statuses and when it was last checked. Every custom domain is looked up about once a day, whatever its DNS provider. See Domain registration expiry.

Path parameters

uuid string (uuid) Req
The domain's uuid from /domains/available.

Response (200 OK)

domain_uuid string (uuid)
The domain's uuid.
name string
Fully-qualified domain (e.g. example.com).
provider string
DNS provider slug (e.g. cloudflare).
status string
The domain's lifecycle status: pending_cname | awaiting_cert (manual mode) | pending_issuance | issuing | active | issuance_failed | renewal_failed | revoked | expired (registration expired, domain suspended — see expiry_suspension). See Domain status.
provisioning_mode string
auto | manual.
issuance_error string?
Error from the most recent failed issuance. Omitted when there is none.
last_issuance_at datetime?
When a certificate was last issued. Omitted if none has been issued yet.
quota_paused boolean
true while the domain is paused because the account is over its plan's custom-domain count — kept, but not served or used.
expiry_suspension object?
Present only while the domain is suspended because its registration expired (status: "expired"); absent otherwise. Holds suspended_at, expires_at (the stored registration expiry, as in registration.expires_at), deletes_at (suspended_at + 30 days), recheck_interval_hours (4), check_again_available, check_state (idle | requested | running), last_checked_at, last_check_outcome (still_expired | lookup_failed | unsupported | account_suspended | error), check_requested_at and next_check_allowed_at. Field by field: the expiry_suspension object. After Check again, check_state goes requested → running → idle with a last_check_outcome; when the renewal is found, the domain is no longer suspended — status is back to what it was and expiry_suspension disappears.
registration object?
The domain's registration as last looked up: expires_at, source, statuses, not_renewed_status, checked_at, lookup_error. Field by field: the registration object. Absent while registration lookups aren't enabled on the platform yet.
latest_job object?
The most recent ACME job for the domain: {job_type, status, attempt_count, max_attempts, last_error}. job_type is e.g. issue or renew; status is pending | running | completed | failed. Omitted when the domain has no jobs.

Deprecated: until the sunset this response also carries the legacy integer domain_id (and an internal latest_job.id). Don't use them; read domain_uuid.

The registration object

What the platform last learned about the domain's registration. It reads every custom domain's registration about once a day (a new domain within about 15 minutes), whatever its DNS provider: from the Cloudflare Registrar record when the DNS provider is Cloudflare and Cloudflare has one, otherwise from RDAP (the TLD registry's server, found via the IANA RDAP bootstrap), otherwise from WHOIS (TLDs without RDAP). It is returned by this endpoint, on the items of GET /v1/domains/self and on your account's own domains in GET /v1/domains/available. Absent while registration lookups aren't enabled on the platform yet.

expires_at datetime | null
The registration expiry the expiry reminders (30, 14 and 7 days before) use; null = unknown. A date the registry reports together with a not_renewed_status is not taken at face value: during the registry's auto-renew grace this stays the old date.
source string?
Where the last successful lookup read the registration: rdap | whois | cloudflare (Cloudflare Registrar). Absent until a lookup has succeeded.
statuses string[]
The registry's EPP statuses from the last successful lookup, as lowercase words (e.g. client transfer prohibited, auto renew period). Empty when none were reported.
not_renewed_status string?
The first of auto renew period | redemption period | pending delete | pending restore | client hold | server hold present in statuses. Many registries move the expiration date a year forward on the expiry day even if nobody has paid (the auto-renew grace period, up to 45 days); while one of these statuses is present, the registry's date is not treated as a renewal — the dashboard shows "Registry: <status> — not renewed yet". Absent when none is present. A renewal counts only when the new date is more than 7 days in the future and there is no not_renewed_status.
checked_at datetime?
When the registration was last looked up, successfully or not. Absent before the first lookup.
lookup_error string?
Why the last lookup failed (e.g. the registry has no record of this domain) — the dashboard shows "Couldn't check the registration" with this reason. Absent when the last lookup succeeded. A failed or empty lookup never suspends the domain.

In the "registry auto-renew grace" example, the registry already shows next year's date, but auto renew period means it isn't paid yet: expires_at stays the old date, the domain keeps working, and the expiry reminders don't stop.

Errors

401 Unauthorized
Missing auth.
404 Not Found
Domain doesn't exist or doesn't belong to your active account.
Request
curl "https://api.ngris.com/v1/domains/self/019bd08f-98db-71b2-8e54-f518d319f111/acme/status" \ -H "X-API-KEY: <your_api_key>"
Python
from ngris import Ngris client = Ngris(api_key="<your_api_key>") status = client.domains.get_acme_status("019bd08f-98db-71b2-8e54-f518d319f111") if status["status"] in ("issuance_failed", "renewal_failed"): print("ACME failed:", status.get("issuance_error")) elif "expiry_suspension" in status: print("Registration expired; deleted at", status["expiry_suspension"]["deletes_at"]) reg = status.get("registration") or {} if reg.get("not_renewed_status"): print("Registry:", reg["not_renewed_status"], "- not renewed yet") elif reg.get("lookup_error"): print("Couldn't check the registration:", reg["lookup_error"])
Response — active
{ "domain_uuid": "019bd08f-98db-71b2-8e54-f518d319f111", "name": "example.com", "provider": "cloudflare", "status": "active", "provisioning_mode": "auto", "last_issuance_at": "2026-09-15T08:23:00Z", "quota_paused": false, "registration": { "expires_at": "2027-03-14T00:00:00Z", "source": "rdap", "statuses": ["client transfer prohibited"], "checked_at": "2026-09-30T06:12:09Z" }, "latest_job": { "job_type": "renew", "status": "completed", "attempt_count": 1, "max_attempts": 5 } }
Response — suspended (registration expired)
{ "domain_uuid": "019bd08f-98db-71b2-8e54-f518d319f111", "name": "example.com", "provider": "cloudflare", "status": "expired", "provisioning_mode": "auto", "last_issuance_at": "2026-09-15T08:23:00Z", "quota_paused": false, "expiry_suspension": { "suspended_at": "2026-09-28T00:05:12Z", "expires_at": "2026-09-28T00:00:00Z", "deletes_at": "2026-10-28T00:05:12Z", "recheck_interval_hours": 4, "check_again_available": true, "check_state": "idle", "last_checked_at": "2026-09-30T09:12:44Z", "last_check_outcome": "still_expired", "check_requested_at": "2026-09-30T09:12:40Z", "next_check_allowed_at": "2026-09-30T09:22:40Z" }, "registration": { "expires_at": "2026-09-28T00:00:00Z", "source": "cloudflare", "statuses": [], "checked_at": "2026-09-30T09:12:44Z" }, "latest_job": { "job_type": "renew", "status": "completed", "attempt_count": 1, "max_attempts": 5 } }
Response — registry auto-renew grace (not renewed yet)
{ "domain_uuid": "019bc620-2ae3-70ae-a5bd-6c3b5e250242", "name": "example.org", "provider": "route53", "status": "active", "provisioning_mode": "auto", "last_issuance_at": "2026-09-15T08:23:00Z", "quota_paused": false, "registration": { "expires_at": "2026-09-28T00:00:00Z", "source": "rdap", "statuses": ["auto renew period", "client transfer prohibited"], "not_renewed_status": "auto renew period", "checked_at": "2026-09-30T06:12:09Z" }, "latest_job": { "job_type": "renew", "status": "completed", "attempt_count": 1, "max_attempts": 5 } }
Was this helpful?
Was this helpful?