---
title: "Create an asset"
method: POST
path: "/v1/assets"
tags: ["Assets"]
---

# Create an asset

`POST /v1/assets`

## Request

- Base URL: `https://api.merlonix.com`
- URL: `https://api.merlonix.com/v1/assets`
- Auth: HTTP bearer

Register a new monitored asset. Requires a `write`-scoped key. Enforces the plan asset quota and the per-tier minimum check interval; a hostname that fails the abuse filter is rejected (`422`). TD-2480: if this hostname was previously deleted, the existing (soft-deleted) asset is RESTORED with its full check history rather than a new one being created — the response is `200` with `revived: true` and the ORIGINAL asset id. A `409` therefore means an asset you can still see in `GET /v1/assets` already has this hostname and type.

## Request body

- AssetCreate: Request body for creating a monitored asset (TD-925).
  - `asset_type` 'domain' | 'hostname' | 'certificate' | 'dns_record', required
  - `hostname` string, required: The hostname / domain to monitor.
  - `attestation_id` string, uuid: Optional ownership attestation; must belong to the tenant.
  - `label` string: Optional human label.
  - `client_name` string
  - `client_id` string, uuid: Optional client bucket; defaults to Unassigned.
  - `check_interval_sec` integer: Check cadence. Clamped up to the plan minimum if faster than the tier allows.
  - `ssl_enabled` boolean
  - `dns_enabled` boolean
  - `domain_enabled` boolean: Opt into monitored domain-expiry (RDAP) checks.
  - `dnsbl_enabled` boolean: Opt into monitored DNS-blocklist (DNSBL) checks.
  - `dns_security_enabled` boolean: Opt into monitored DNSSEC + DANE/TLSA posture checks (informational).
  - `security_headers_enabled` boolean: Opt into the monitored HTTP security-header check (re-grades the six core headers on cadence + alerts when one disappears; informational).
  - `email_auth_enabled` boolean: Opt into the monitored email-auth (SPF/DMARC/MTA-STS/BIMI) posture check.
  - `ct_watch_enabled` boolean: Opt into Certificate-Transparency rogue/shadow-cert monitoring. Paid monitoring tiers only (team/agency/compliance).
  - `agent_readiness_enabled` boolean: Opt into monitored Agent-Readiness checks.
  - `mcp_health_enabled` boolean: Opt into monitored MCP-server health checks (discovers the MCP endpoint from /.well-known/mcp.json and runs a real JSON-RPC handshake + tools/list; alerts on downtime and tool/schema drift).
  - `heartbeat_enabled` boolean: Opt into the inbound heartbeat (dead-man's-switch) monitor. The ingest token is server-minted on first enable.
  - `heartbeat_period_sec` integer: Expected heartbeat interval in seconds.
  - `heartbeat_grace_sec` integer: Tolerance in seconds before a missed beat is declared dead.
  - `port_enabled` boolean: Opt into the outbound TCP-port monitor.
  - `port_check_port` integer: TCP port to probe on the asset's hostname.
  - `psi_enabled` boolean: Opt into the PageSpeed Insights (Lighthouse) performance monitor. Paid monitoring tiers only (team/agency/compliance).
  - `psi_check_url` string, uri: Optional override URL to measure with PageSpeed Insights (defaults to https://<hostname>).
  - `health_enabled` boolean: Opt into the application-health monitor (polls a JSON health endpoint). Paid monitoring tiers only (team/agency/compliance).
  - `health_check_url` string, uri: JSON health endpoint to poll (laravel-health / Oh Dear shape, with a generic fallback). SSRF-guarded.
  - `health_check_config` object: TD-941 application-health config. headers: auth header(s) sent with the GET (≤10, envelope headers rejected, values never logged); stale_after_sec: freshness window in seconds (30..86400, default 600).
    - `headers` object
    - `stale_after_sec` integer
  - `crawl_enabled` boolean: Opt into the broken-links / mixed-content crawler. Paid monitoring tiers only (team/agency/compliance).
  - `crawl_root_url` string, uri: Optional crawl root URL (defaults to https://<hostname>).
  - `injection_scan_enabled` boolean: Opt into the prompt-injection / hidden-text scan (computed-DOM render). Paid monitoring tiers only (team/agency/compliance).
  - `uptime_check_url` string, uri: Enables HTTP uptime checks when set (GET probe). For method/headers/body/redirect assertions use uptime_check_config.
  - `uptime_check_config` object: TD-935 structured uptime probe (wins over uptime_check_url). method=GET|HEAD|POST|PUT|PATCH; optional custom headers (≤20, forbidden envelope headers rejected), body (≤8KiB, body-bearing methods only), expected_status, keyword_match, and expected_final_url (redirect-target assertion — DOWN if the final URL after one redirect hop differs). Timing reported: ttfb_ms (headers received) and response_time_ms (total/body read). Cloudflare Workers fetch() exposes no DNS/TCP/TLS phase breakdown, so those are not reported.
    - `check_url` string, uri, required
    - `method` 'GET' | 'HEAD' | 'POST' | 'PUT' | 'PATCH'
    - `expected_status` integer
    - `keyword_match` string, nullable
    - `timeout_ms` integer
    - `headers` object, nullable
    - `body` string, nullable
    - `expected_final_url` string, uri, nullable
  - `vendor_dependencies` string[]

## Response `200`

A previously-deleted asset with this hostname was restored (TD-2480). The id is the ORIGINAL asset id and its check history is intact.

- object
  - `asset` Asset, required
    - `id` string, uuid, required
    - `tenant_id` string, uuid, required
    - `attestation_id` string, uuid, nullable, required
    - `asset_type` 'domain' | 'hostname' | 'certificate' | 'dns_record', required
    - `hostname` string, required
    - `label` string, nullable, required
    - `client_name` string, nullable, required
    - `client_id` string, uuid, nullable, required
    - `check_interval_sec` integer, required
    - `ssl_enabled` boolean, required
    - `dns_enabled` boolean, required
    - `uptime_enabled` boolean, required
    - `domain_enabled` boolean, required
    - `dnsbl_enabled` boolean, required
    - `dns_security_enabled` boolean, required
    - `security_headers_enabled` boolean, required
    - `email_auth_enabled` boolean, required
    - `ct_watch_enabled` boolean, required
    - `agent_readiness_enabled` boolean, required
    - `mcp_health_enabled` boolean, required
    - `heartbeat_enabled` boolean, required
    - `heartbeat_period_sec` integer, nullable, required
    - `heartbeat_grace_sec` integer, nullable, required
    - `heartbeat_token` string, nullable, required
    - `port_enabled` boolean, required
    - `port_check_port` integer, nullable, required
    - `psi_enabled` boolean, required
    - `psi_check_url` string, nullable, required
    - `last_psi_at` string, date-time, nullable, required
    - `health_enabled` boolean, required
    - `health_check_url` string, nullable, required
    - `health_check_config` object, nullable, required: TD-941 application-health monitor config ({ headers?, stale_after_sec? }); null when not configured.
    - `crawl_enabled` boolean, required
    - `crawl_root_url` string, nullable, required
    - `last_crawl_at` string, date-time, nullable, required
    - `injection_scan_enabled` boolean, required
    - `injection_scan_last_at` string, date-time, nullable, required
    - `uptime_check_url` string, nullable, required
    - `uptime_check_config` object, nullable, required: TD-935 structured uptime probe config (method/headers/body/expected_status/keyword_match/expected_final_url); null when uptime is not configured.
    - `is_active` boolean, required
    - `paused_reason` string, nullable, required
    - `vendor_dependencies` string[], required
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
    - `last_checked_at` string, date-time, nullable, required
  - `revived` true, required

## Other responses

- `201`: The created asset.
- `400`: Error — canonical envelope with a trace_id.
- `401`: Error — canonical envelope with a trace_id.
- `402`: Error — canonical envelope with a trace_id.
- `403`: Error — canonical envelope with a trace_id.
- `409`: Error — canonical envelope with a trace_id.
- `422`: Error — canonical envelope with a trace_id.
- `429`: Error — canonical envelope with a trace_id.

---

[API](https://skmtc.dev/merlonix/apis/merlonix-public-api.md) · [All operations](https://skmtc.dev/merlonix/apis/merlonix-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/merlonix/apis/merlonix-public-api/revisions/2192584bdfcd?raw)
