Skip to content

REST API Domains

Ed Mozley edited this page Oct 4, 2026 · 3 revisions

🌐 REST API: Domains

The usage guide for the Domains module of the REST API: the domain register, registry lookups, the security checks and their findings, and each domain's history. Mirrors the interactive documentation at System β†’ API β†’ Documentation.

Note

New to the API? The basics table on REST API: Tickets covers base URL, authentication, the response envelope, error codes, rate limits and PATCH semantics - identical across all modules.

What's distinctive about Domains:

🏒 Company-scoped Lists are filtered to the key's companies; a domain outside them is a 404 on every by-id route. New domains land in company_id (checked against the key) or the key's default company.
πŸ” Auth codes never cross the API Responses carry only auth_code_set; a body containing auth_code is refused with 422. A transfer secret belongs behind the analyst permission and its audit trail.
πŸ”Ž Lookups and checks on demand POST /domains/{id}/lookup asks the registry now; POST /domains/{id}/check re-grades now. Both return the domain with what changed.
πŸ“œ Findings in English GET /domains/{id}/findings returns each finding's title and advice filled in, for a consumer with no language file.

Give a key the Domains permissions (read / create / update / delete) under System β†’ API.


πŸš€ Quick start

B="https://your-server/api/v1"; K="Authorization: Bearer fitsm_…"

# Everything expiring in the next 60 days, soonest first
curl -s -H "$K" "$B/domains?expiring_within_days=60&sort=expiry_date" | jq '.data[] | {domain_name, expiry_date, days_remaining}'

# Add a domain and fill in the registry details straight away
curl -s -H "$K" -H "Content-Type: application/json" -X POST \
     -d '{"domain_name":"example.com","purpose":"primary","lookup":true}' "$B/domains"

# What is wrong with it, and how to fix it
curl -s -H "$K" "$B/domains/42/findings" | jq '.data[] | select(.level=="fail" or .level=="warn") | {title, advice}'

Endpoints

Method Path Permission What
GET /domains domains.read List / search
POST /domains domains.create Add a domain
GET /domains/{id} domains.read One domain
PATCH /domains/{id} domains.update Change fields
DELETE /domains/{id} domains.delete Delete (with its history)
POST /domains/{id}/lookup domains.update Refresh from the registry
POST /domains/{id}/check domains.update Run the checks now
GET /domains/{id}/findings domains.read The last check's findings
GET /domains/{id}/history domains.read Every change, newest first
GET /domain-statuses domains.read Statuses (alerts_enabled marks the ones that stop reminders)
GET /domain-registrar-accounts domains.read Registrar accounts (company-scoped; no passwords exist to return)

List filters

q, domain_name (tidied like input, so a URL matches), status_id, owner_analyst_id, registrar_supplier_id, registrar_account_id, purpose, tag, expiring_within_days, expired=true, transfer_lock=true|false, grade=D,F, company_id, sort (expiry_date default, domain_name, security_score, ssl_expiry_date, created_at, id; prefix - for descending), page / per_page.

Writes

Only domain_name is required on create. Lookups (status_id, owner_analyst_id, registrar_supplier_id, registrar_account_id, tech_contact_id, tech_analyst_id, contract_id, customer_user_id, customer_supplier_id, customer_contact_id) are validated with a 422 naming the field. customer_user_id is the domain's customer β€” a user in the domain's own company β€” and comes back as customer: {id, name, email}.

Customer and technical contact (3.1.0, #162). A domain has one customer β€” customer_user_id, or customer_supplier_id with an optional customer_contact_id β€” and one technical contact β€” tech_contact_id (a supplier contact) or tech_analyst_id. Setting one kind clears the other, so a PATCH need only name the new one; naming both kinds in one request is a 422. A customer_contact_id on its own sets customer_supplier_id to that contact's supplier; a contact from a different supplier than the one you name is a 422. Clearing customer_supplier_id clears its contact too. The responses keep customer and tech_contact exactly as before and add tech_analyst: {id, name}, customer_supplier: {id, name} and customer_contact: {id, name, email} beside them, each null when not set. Before Database Verification has added the columns, the three new fields are accepted and ignored. Dates are YYYY-MM-DD. purpose is one of primary, secondary, redirect, email_only, defensive, parked, campaign; renewal_mode one of auto, manual, do_not_renew, unknown. On PATCH, omit a field to leave it, send "" or null to clear it.

Every write goes through the same service as the screens: the same validation, a history row per changed field (source api), and the domain.created / domain.updated / domain.deleted workflow events.

Errors

HTTP code When
400 invalid_parameter unknown sort or purpose
403 forbidden company_id outside the key's scope
404 not_found no such domain, or outside the key's companies
409 conflict the name is already in the register for that company
422 invalid_field / missing_field bad value, unknown id, empty PATCH - or auth_code in the body
502 lookup_failed the registry did not answer, rate-limited, or has no such registration

See also: Domains Β· Domains developer guide Β· REST API

FreeITSM

Getting Started

Modules

Multi-tenancy (planned)

Blue sky thinking

Bugs resolved

Links

Clone this wiki locally