API Integration Reference
The Merlonix API is a REST API over HTTPS. It enables agencies to automate asset provisioning, trigger checks, create attestations, and pull monitoring data into external tools — project management systems, reporting dashboards, client portals.
Base URL
https://api.merlonix.com/v1
All endpoints require authentication.
Authentication
The API uses Bearer token authentication. Include your JWT in every request:
Authorization: Bearer <your-token>
Obtaining a token: Navigate to Settings → API in the Merlonix app to generate an API token. Tokens are scoped to your tenant and inherit the permissions of the user who created them.
Token expiry: API tokens are long-lived by default. Rotate them from Settings → API if you suspect a token has been compromised.
Request and response format
- All request bodies are JSON (
Content-Type: application/json) - All responses are JSON
- Timestamps are ISO 8601 UTC:
2026-04-30T09:14:00Z
Error format
{
"error": "bad_request",
"message": "hostname is required",
"issues": [
{ "path": "hostname", "issue": "Required" }
]
}
Common status codes:
| Code | Meaning |
|---|---|
200 | Success |
201 | Created |
400 | Validation error (see issues) |
401 | Missing or invalid token |
403 | Authenticated but not authorised |
404 | Resource not found or not in your tenant |
429 | Rate limit exceeded |
Pagination
List endpoints return paginated results.
Request parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 50 | Max records per page (1–100) |
offset | integer | 0 | Records to skip |
Response shape:
{
"data": [...],
"total": 142,
"limit": 50,
"offset": 0
}
Assets
Assets are the core monitoring unit: a hostname or IP address that Merlonix monitors for SSL and DNS health.
List assets
GET /v1/assets
Query parameters: limit, offset
Response:
{
"data": [
{
"id": "uuid",
"label": "Client A — main site",
"hostname": "clienta.com",
"check_interval_minutes": 60,
"ssl_monitoring": true,
"dns_monitoring": true,
"created_at": "2026-01-15T10:00:00Z"
}
],
"total": 12,
"limit": 50,
"offset": 0
}
Create an asset
POST /v1/assets
Request body:
{
"label": "Client A — main site",
"hostname": "clienta.com",
"check_interval_minutes": 60,
"ssl_monitoring": true,
"dns_monitoring": true
}
| Field | Type | Required | Notes |
|---|---|---|---|
label | string | Yes | Human-readable name |
hostname | string | Yes | Domain or IP to monitor |
check_interval_minutes | integer | No | 5, 15, 30, or 60 (default: 60) |
ssl_monitoring | boolean | No | Default: true |
dns_monitoring | boolean | No | Default: true |
Response: 201 Created with the created asset object.
Asset limits: Asset creation fails if your plan's asset limit is reached. Check GET /v1/customers/me for asset_limit and current usage.
Get an asset
GET /v1/assets/:id
Returns a single asset with the same shape as the list response, plus the latest check summary.
Update an asset
PATCH /v1/assets/:id
All fields are optional. Omitted fields are unchanged.
{
"label": "Client A — shop (updated)",
"check_interval_minutes": 5
}
Delete an asset
DELETE /v1/assets/:id
Deletes the asset and all associated check history. This is irreversible.
Response: 200 OK with { "deleted": true }.
Trigger an immediate check
POST /v1/assets/:id/check-now
Enqueues an out-of-cycle check for the asset. The check runs within 60 seconds.
Response: 200 OK with a trace ID you can use to correlate the check result in GET /v1/checks.
Attestations
Attestations are tamper-evident certificates tied to an asset. See Attestation Deep Dive for a full explanation of verification methods and certificate contents.
List attestations
GET /v1/attestations
Query parameters: limit, offset, asset_id (optional filter)
Create an attestation
POST /v1/attestations
{
"asset_id": "uuid",
"statement": "Logo pack v3 — approved by client on 2026-04-29",
"method": "inline"
}
| Field | Type | Required | Notes |
|---|---|---|---|
asset_id | uuid | Yes | Asset to attest |
statement | string | Yes | Description of what is being certified |
method | string | Yes | inline, dns_txt, or http_file |
For dns_txt and http_file methods, the response includes a challenge object:
{
"id": "uuid",
"status": "pending",
"challenge": {
"method": "dns_txt",
"hostname": "_merlonix-verify.clienta.com",
"record_type": "TXT",
"token": "merlonix-verify=abc123xyz"
}
}
Place the challenge in DNS or serve the file, then call POST /v1/attestations/:id/verify to complete verification (or wait — Merlonix polls automatically every 30 seconds for up to 10 minutes).
Get an attestation
GET /v1/attestations/:id
Returns the full certificate including verification status, state hash, and the public verification URL.
Revoke an attestation
POST /v1/attestations/:id/revoke
{
"reason": "Superseded by v4 delivery"
}
The reason is optional but displayed on the public verification URL and logged in the audit trail.
Checks
Checks are the time-series record of SSL and DNS monitoring results for each asset.
List check history
GET /v1/checks?asset_id=<uuid>
Query parameters:
| Parameter | Type | Notes |
|---|---|---|
asset_id | uuid | Required |
check_type | string | ssl or dns (optional filter) |
limit | integer | Default 50, max 100 |
offset | integer | Default 0 |
Response:
{
"data": [
{
"id": "uuid",
"asset_id": "uuid",
"check_type": "ssl",
"classifier": "expiring_soon",
"severity": "warning",
"detail": { "days_remaining": 22, "issuer": "Let's Encrypt" },
"checked_at": "2026-04-30T09:00:00Z"
}
]
}
Get latest check per asset
GET /v1/checks/latest?asset_id=<uuid>
Returns the most recent SSL check result and the most recent DNS check result for the asset. Useful for dashboard-style status polling.
Alert channels
Channels define where Merlonix sends notifications. See Alert Channels for the full reference on severity filters and routing.
List channels
GET /v1/channels
Create a channel
POST /v1/channels
{
"type": "slack",
"config": {
"webhook_url": "https://hooks.slack.com/services/..."
},
"severity_filter": "warning"
}
| Field | Type | Notes |
|---|---|---|
type | string | email, slack, or webhook |
config | object | Type-specific config (see below) |
severity_filter | string | info, warning, or critical |
Config by type:
// email
{ "address": "[email protected]" }
// slack
{ "webhook_url": "https://hooks.slack.com/services/..." }
// webhook
{ "url": "https://your-endpoint.com/hook", "secret": "optional-signing-secret" }
For webhook type, the response includes the generated signing secret. Store it securely — it is shown only once.
Update a channel
PATCH /v1/channels/:id
Accepts the same fields as create. Omitted fields are unchanged.
Delete a channel
DELETE /v1/channels/:id
Account
Get account details
GET /v1/customers/me
Returns tenant details including plan, asset count, asset limit, and current stack tags.
{
"id": "uuid",
"name": "Your Agency",
"billing_email": "[email protected]",
"plan": "starter",
"asset_count": 12,
"asset_limit": 25,
"stack_tags": ["payments.checkout", "network.cdn"],
"trial_ends_at": null,
"created_at": "2026-01-01T00:00:00Z"
}
Update account details
PATCH /v1/customers/me
{
"name": "Your Agency",
"billing_email": "[email protected]",
"timezone": "America/New_York",
"stack_tags": ["payments.checkout", "payments.webhooks", "network.cdn"]
}
All fields are optional. stack_tags is a full replacement — send the complete list you want active. See Vendor Stack Tags for the full tag catalog.
Automation patterns
Provisioning a client on signup
// 1. Create the asset
const asset = await api.post('/v1/assets', {
label: `${clientName} — main site`,
hostname: clientDomain,
check_interval_minutes: 60,
});
// 2. Trigger the first check immediately
await api.post(`/v1/assets/${asset.id}/check-now`);
// 3. Create an alert channel for the client
await api.post('/v1/channels', {
type: 'email',
config: { address: clientContactEmail },
severity_filter: 'critical',
});
Pulling check data into a report
// Get the latest check for every asset
const assets = await api.get('/v1/assets?limit=100');
const statuses = await Promise.all(
assets.data.map(a => api.get(`/v1/checks/latest?asset_id=${a.id}`))
);
// statuses[i] has ssl and dns check results for assets.data[i]
Creating an attestation on deliverable approval
const cert = await api.post('/v1/attestations', {
asset_id: assetId,
statement: `${deliverableName} — approved by ${clientName} on ${date}`,
method: 'inline',
});
// cert.verification_url is the shareable public link
await sendDeliverableEmail({ ...deliverable, certificateUrl: cert.verification_url });
Rate limits
The API applies per-tenant rate limits:
| Tier | Requests per minute |
|---|---|
| Starter | 60 |
| Agency | 300 |
When a limit is exceeded, the API returns 429 Too Many Requests with a Retry-After header indicating when the limit resets.
Next: return to Getting Started or read Vendor Stack Tags to configure which vendor incidents appear in your monitoring data.