---
title: "API reference · urlert"
description: "Every operation of the URLert API: what you send, what you get back and an example call."
url: https://www.urlert.com/developers/reference
mcp: https://www.urlert.com/mcp
---

# URLert API, v1

The URLert API, version 1 (a beta). It checks a link, a message or a page before a program or an AI assistant acts on it, with the same checks as the website. There are six operations, each a POST with a JSON body, with a token made in Account, then AI agents, sent as `Authorization: Bearer <token>`. There is no operation that deletes a check or an account or changes how you sign in.

`check_link` `check_message` `check_page` `get_result` `get_guide` `report_mistake` Errors

## The result

Every answer of a check has the same fields. Every field is always there, `null` or an empty list when it has nothing to say.

`status`

A closed list. Call get_result until it is done or failed; a failed check is still a 200 answer.

`queued` `running` `done` `failed`

`outcome`

A closed list. Null until the check is done.

`malicious` `scam` `risky` `suspicious` `nothing_found` `cant_tell`

`failure`

An open list. Null unless the check failed.

`unavailable` `our_limit` `too_long`

`views[].state`

An open list.

`picture` `blank` `human_check` `provider_warning` `refused` `unsupported` `gone` `file` `failed` `no_response` `cut_off` `slow` `no_dns` `cert` `not_opened` `our_limit` `daily_limit` `site_error`

## Every call

`Address`

Every operation is a POST with a JSON body to https://www.urlert.com/api/v1/\<operation\>.

`Token`

`Authorization: Bearer <token>`, a token made in Account, then AI agents.

A call is `POST /api/v1/<operation>`. A check answers at once with `status` `queued`: call `get_result` every few seconds with its `id` until `status` is `done` or `failed`. A check that fails is still a 200 answer; read `failure`. The limit is 20 checks a day for each account, across the API and the AI assistants' tools together; `get_result`, `get_guide` and `report_mistake` don't count, and the count starts again at 00:00 UTC. `RateLimit` and `RateLimit-Policy` headers describe the API's call rate, not the daily limit. Send an `Idempotency-Key` with a check or a report: a repeat of the same call gives back the first answer and doesn't count again. This is a beta: a change that would break a program gets a version 2, and version 1 is retired with a date announced in advance.

Every failure is `application/problem+json` with `status`, `code`, `detail` (words for a person) and `errors` (the fields at fault). Branch on `code`. A 400 `bad_request` means fix the request. A 400 `invalid_text` means send the message's text. A 401 `invalid_token` means make a new token. A 403 `insufficient_scope` means the token isn't allowed this operation. A 404 `not_found` says "No check has this id. Checks are deleted after 30 days." and means stop polling. A 409 `no_result_yet` says "This check has no result to report yet" and means wait until the check is done. A 429 `daily_limit` says "This account has made 20 checks today. The limit is 20 a day. The count starts again at 00:00 UTC." and a 429 `checks_paused` says "Checks from assistants and programs are paused until 00:00 UTC. The website still works for people."; both send `Retry-After`, the seconds until 00:00 UTC, so wait that long and don't spread the calls over more accounts. A 429 `rate_limited` also sends `Retry-After`: slow down. A 500 or 503 is ours: retry with backoff, and the checks are safe to retry with an `Idempotency-Key`.

## check_link

Checks one link before you open it or act on it. Answers at once with the check's `id` and status `queued`: call get_result with the id until its status is `done` or `failed`. Counts as one of the account's 20 checks a day. Can answer 400 `bad_request` (the link isn't one web link, or `country` isn't two capital letters), 429 `daily_limit` or 429 `checks_paused`.

`link` text

required

`action` text or null

optional

`task` text or null

optional

`country` text or null

optional

`checks_paused` 429

Checks from assistants and programs are paused until 00:00 UTC. The website still works for people.

`daily_limit` 429

This account has made 20 checks today. The limit is 20 a day. The count starts again at 00:00 UTC.

`POST` `https://www.urlert.com/api/v1/check_link`

Request

```
curl -X POST https://www.urlert.com/api/v1/check_link -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" -d '{"link":"link","action":"action","task":"task","country":"country"}'
```

Answer

```
{
  "id": "id",
  "status": "queued",
  "outcome": "malicious",
  "outcome_name": "outcome_name",
  "asks_for": [
    "asks_for"
  ],
  "reasons": [
    {
      "text": "text"
    }
  ],
  "sites": [
    {
      "host": "host",
      "domain": "domain",
      "age_days": 3,
      "age_note": "age_note",
      "anyone_can_publish": true,
      "scam_lists": [
        "scam_lists"
      ]
    }
  ],
  "opened_link": "opened_link",
  "final_link": "final_link",
  "views": [
    {
      "device": "device",
      "state": "state"
    }
  ],
  "reused": true,
  "checked_at": "2030-01-15T09:30:00.000Z",
  "expires_at": "2030-01-15T09:30:00.000Z",
  "failure": "failure",
  "message": "message",
  "shared_copy": true,
  "result_url": "result_url"
}
```

## check_message

Checks the text of a message, and the links in it. Answers at once with the check's `id`: call get_result until its status is `done` or `failed`. Counts as one of the account's 20 checks a day. Can answer 400 `bad_request` (the message is over 5,000 characters, the sender over 200, or `country` isn't two capital letters), 400 `invalid_text` (send the message's text), 429 `daily_limit` or 429 `checks_paused`.

`text` text

required

`sender` text or null

optional

`source` text or null

optional

`action` text or null

optional

`task` text or null

optional

`country` text or null

optional

`checks_paused` 429

Checks from assistants and programs are paused until 00:00 UTC. The website still works for people.

`daily_limit` 429

This account has made 20 checks today. The limit is 20 a day. The count starts again at 00:00 UTC.

`invalid_text` 400

Send the message's text.

`POST` `https://www.urlert.com/api/v1/check_message`

Request

```
curl -X POST https://www.urlert.com/api/v1/check_message -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" -d '{"text":"text","sender":"sender","source":"source","action":"action","task":"task","country":"country"}'
```

Answer

```
{
  "id": "id",
  "status": "queued",
  "outcome": "malicious",
  "outcome_name": "outcome_name",
  "asks_for": [
    "asks_for"
  ],
  "reasons": [
    {
      "text": "text"
    }
  ],
  "sites": [
    {
      "host": "host",
      "domain": "domain",
      "age_days": 3,
      "age_note": "age_note",
      "anyone_can_publish": true,
      "scam_lists": [
        "scam_lists"
      ]
    }
  ],
  "opened_link": "opened_link",
  "final_link": "final_link",
  "views": [
    {
      "device": "device",
      "state": "state"
    }
  ],
  "reused": true,
  "checked_at": "2030-01-15T09:30:00.000Z",
  "expires_at": "2030-01-15T09:30:00.000Z",
  "failure": "failure",
  "message": "message",
  "shared_copy": true,
  "result_url": "result_url"
}
```

## check_page

Checks a page from your own view of it, which we don't open. The views say `not_opened`. Counts as one of the account's 20 checks a day. Can answer 400 `bad_request` (the link isn't one web link, or `page_text` is empty or over 20,000 characters), 429 `daily_limit` or 429 `checks_paused`.

`link` text

required

`page_text` text

required

`action` text or null

optional

`task` text or null

optional

`checks_paused` 429

Checks from assistants and programs are paused until 00:00 UTC. The website still works for people.

`daily_limit` 429

This account has made 20 checks today. The limit is 20 a day. The count starts again at 00:00 UTC.

`POST` `https://www.urlert.com/api/v1/check_page`

Request

```
curl -X POST https://www.urlert.com/api/v1/check_page -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" -d '{"link":"link","page_text":"page_text","action":"action","task":"task"}'
```

Answer

```
{
  "id": "id",
  "status": "queued",
  "outcome": "malicious",
  "outcome_name": "outcome_name",
  "asks_for": [
    "asks_for"
  ],
  "reasons": [
    {
      "text": "text"
    }
  ],
  "sites": [
    {
      "host": "host",
      "domain": "domain",
      "age_days": 3,
      "age_note": "age_note",
      "anyone_can_publish": true,
      "scam_lists": [
        "scam_lists"
      ]
    }
  ],
  "opened_link": "opened_link",
  "final_link": "final_link",
  "views": [
    {
      "device": "device",
      "state": "state"
    }
  ],
  "reused": true,
  "checked_at": "2030-01-15T09:30:00.000Z",
  "expires_at": "2030-01-15T09:30:00.000Z",
  "failure": "failure",
  "message": "message",
  "shared_copy": true,
  "result_url": "result_url"
}
```

## get_result

A check's result by its id. Does not count against the day's 20 checks. Answers 404 `not_found` for an id nobody has, or one whose 30 days are over.

`id` text

required

`POST` `https://www.urlert.com/api/v1/get_result`

Request

```
curl -X POST https://www.urlert.com/api/v1/get_result -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" -d '{"id":"id"}'
```

Answer

```
{
  "id": "id",
  "status": "queued",
  "outcome": "malicious",
  "outcome_name": "outcome_name",
  "asks_for": [
    "asks_for"
  ],
  "reasons": [
    {
      "text": "text"
    }
  ],
  "sites": [
    {
      "host": "host",
      "domain": "domain",
      "age_days": 3,
      "age_note": "age_note",
      "anyone_can_publish": true,
      "scam_lists": [
        "scam_lists"
      ]
    }
  ],
  "opened_link": "opened_link",
  "final_link": "final_link",
  "views": [
    {
      "device": "device",
      "state": "state"
    }
  ],
  "reused": true,
  "checked_at": "2030-01-15T09:30:00.000Z",
  "expires_at": "2030-01-15T09:30:00.000Z",
  "failure": "failure",
  "message": "message",
  "shared_copy": true,
  "result_url": "result_url"
}
```

## get_guide

The steps for someone who already acted, most urgent first, or one scam guide. Does not count against the day's 20 checks.

`did` a list of one of

optional

`money` `card` `installed` `remote` `password` `id` `replied` `assistant` `opened`

`scam` one of

optional

`how-scams-pretend` `parcel-toll-tax-fees` `bank-and-card-alerts` `safe-account-scams` `fake-invoices` `prizes-and-refunds` `jobs-and-paid-tasks` `fake-shops` `marketplace` `investments` `crypto-wallets` `threats-and-blackmail` `codes-and-sign-in-requests` `fake-sign-in-pages` `qr-codes` `fake-downloads` `fake-verify-human` `tech-support` `id-theft` `hi-mom-new-number` `online-romance` `call-or-reply` `ai-assistants`

`POST` `https://www.urlert.com/api/v1/get_guide`

Request

```
curl -X POST https://www.urlert.com/api/v1/get_guide -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" -d '{"did":["money"],"scam":"how-scams-pretend"}'
```

Answer

```
{
  "title": "title",
  "steps": [
    {
      "head": "head",
      "body": "body",
      "link": "link"
    }
  ],
  "good_to_know": [
    {
      "head": "head",
      "body": "body",
      "link": "link"
    }
  ],
  "guides": [
    {
      "key": "key",
      "title": "title"
    }
  ],
  "scam": {
    "key": "key",
    "title": "title",
    "summary": "summary",
    "examples": [
      "examples"
    ],
    "signs": [
      {
        "head": "head",
        "body": "body",
        "link": "link"
      }
    ],
    "steps": [
      {
        "head": "head",
        "body": "body",
        "link": "link"
      }
    ],
    "link": "link"
  },
  "scams": [
    {
      "key": "key",
      "title": "title"
    }
  ]
}
```

## report_mistake

Tells us a result is wrong. One report for each check from each account: a second answers 200 with the first one's `sent_at`. Does not count against the day's 20 checks. Can answer 404 `not_found`, or 409 `no_result_yet` while the check has no result.

`id` text

required

`choice` one of

required

`missed` `false_alarm` `other`

`details` text or null

optional, 1 to 1000 characters

`no_result_yet` 409

This check has no result to report yet

`POST` `https://www.urlert.com/api/v1/report_mistake`

Request

```
curl -X POST https://www.urlert.com/api/v1/report_mistake -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" -d '{"id":"id","choice":"missed","details":"details"}'
```

Answer

```
{
  "id": "id",
  "sent_at": "2030-01-15T09:30:00.000Z"
}
```

## Errors

`checks_paused` 429

Checks from assistants and programs are paused until 00:00 UTC. The website still works for people.

`daily_limit` 429

This account has made 20 checks today. The limit is 20 a day. The count starts again at 00:00 UTC.

`invalid_text` 400

Send the message's text.

`no_result_yet` 409

This check has no result to report yet

`invalid_token` 401

The token is unknown, revoked or expired: make another on the app's agents page.

`insufficient_scope` 403

The token is limited to other operations.

`outside_token_record` 403

The token works within one record, and this would change something outside it: outside it, the token reads only what someone signed out reads.

`first_step` 403

Its person hasn't taken the app's first step yet, such as agreeing to its terms: detail says where they take it, in the app.

`step_up` 403

The caller is a member of a record or a holder of an app role that asks more of a sign-in than this session or token showed: need says what, second (a second factor), google (a Google sign-in) or enrol (the person has no second factor yet). Sign in again with it, then make a new token: a token keeps what the sign-in that made it showed.

`token_record_left` 403

The token works within a record its person no longer belongs to, or that's gone. It works again if they rejoin.

`rate_limited` 429

Too many calls: wait the seconds Retry-After says, then try again.

`idempotency_key_in_use` 409

A call with this Idempotency-Key is still running: try again in a second.

`idempotency_key_reused` 422

This Idempotency-Key was used with another body: a new request needs a new key.

`idempotency_unkept` 409

The first call with this Idempotency-Key succeeded, but its answer held a secret, which is never kept: read the result with a query, or make a new request with a new key if repeating it is safe.

`cursor_mismatch` 400

after came from another operation or other params: start again without it.

`version_retired` 410

The version was retired: move to the newest one.

`bad_request` 400

`unauthorized` 401

`payment_required` 402

`forbidden` 403

`not_found` 404

`conflict` 409

`gone` 410

`unprocessable_content` 422

`too_many_requests` 429

`internal_server_error` 500

`service_unavailable` 503
