Paid cron for AI agents: we call your https URL on schedule, signed. No account, paid with x402.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Register a schedule against a destination you have already verified. Idempotent on "name": the same name updates the existing task instead of creating a second one. Creating costs nothing; each delivery ATTEMPT costs one credit.
The https:// destination. It must already be registered and verified — see register_destination.
5 fields, UTC only, one minute at the finest. Operators: * a-b a,b */n a-b/n. Names: SUN-SAT (day), JAN-DEC (month). Macros: @yearly @annually @monthly @weekly @daily @midnight @hourly. Day-of-week is 0-6 with 0 = Sunday; 7 also means Sunday. Write days as names (MON-FRI). Numbers differ between schedulers: Quartz, AWS EventBridge and Cloudflare number Sunday as 1, we and croniter as 0. Translated for you: "?". "?" as a whole day-of-month or day-of-week field becomes "*". A NUMERIC day-of-week next to "?" is refused, because "?" means the expression was written where Sunday is 1. Refused: Quartz L, Quartz W, Quartz #, six fields (seconds), seven fields (year), @reboot, @every, CRON_TZ= prefixes, time zones of any kind — each with a code saying what to send instead.
Your name for the task. Unique among your live tasks; creating with an existing name updates it.
The body we send. Stored in the clear, so it must not carry credentials. A non-string is serialized as JSON.
HTTP method of the delivery. Default POST. GET and HEAD carry no body.
Headers we send with the delivery. Stored ENCRYPTED at rest — put credentials here, never in the body.
How long we wait for your server, 250-2000 ms. Answer 202 and do the work behind it.
The server marks this tool as destructive. Running it may delete or overwrite data on the server or in any account you connected with your headers.
Register a schedule against a destination you have already verified. Idempotent on "name": the same name updates the existing task instead of creating a second one. Creating costs nothing; each delivery ATTEMPT costs one credit.
| Argument | Type | Description |
|---|---|---|
| url* | string | The https:// destination. It must already be registered and verified — see register_destination. |
| body | any | The body we send. Stored in the clear, so it must not carry credentials. A non-string is serialized as JSON. |
| cron* | string | 5 fields, UTC only, one minute at the finest. Operators: * a-b a,b */n a-b/n. Names: SUN-SAT (day), JAN-DEC (month). Macros: @yearly @annually @monthly @weekly @daily @midnight @hourly. Day-of-week is 0-6 with 0 = Sunday; 7 also means Sunday. Write days as names (MON-FRI). Numbers differ between schedulers: Quartz, AWS EventBridge and Cloudflare number Sunday as 1, we and croniter as 0. Translated for you: "?". "?" as a whole day-of-month or day-of-week field becomes "*". A NUMERIC day-of-week next to "?" is refused, because "?" means the expression was written where Sunday is 1. Refused: Quartz L, Quartz W, Quartz #, six fields (seconds), seven fields (year), @reboot, @every, CRON_TZ= prefixes, time zones of any kind — each with a code saying what to send instead. |
| name* | string | Your name for the task. Unique among your live tasks; creating with an existing name updates it. |
| method | string | HTTP method of the delivery. Default POST. GET and HEAD carry no body. |
| headers | object | Headers we send with the delivery. Stored ENCRYPTED at rest — put credentials here, never in the body. |
| timeoutMs | integer | How long we wait for your server, 250-2000 ms. Answer 202 and do the work behind it. |
{
"type": "object",
"required": [
"name",
"cron",
"url"
],
"properties": {
"url": {
"type": "string",
"description": "The https:// destination. It must already be registered and verified — see register_destination."
},
"body": {
"description": "The body we send. Stored in the clear, so it must not carry credentials. A non-string is serialized as JSON."
},
"cron": {
"type": "string",
"description": "5 fields, UTC only, one minute at the finest. Operators: * a-b a,b */n a-b/n. Names: SUN-SAT (day), JAN-DEC (month). Macros: @yearly @annually @monthly @weekly @daily @midnight @hourly. Day-of-week is 0-6 with 0 = Sunday; 7 also means Sunday. Write days as names (MON-FRI). Numbers differ between schedulers: Quartz, AWS EventBridge and Cloudflare number Sunday as 1, we and croniter as 0. Translated for you: \"?\". \"?\" as a whole day-of-month or day-of-week field becomes \"*\". A NUMERIC day-of-week next to \"?\" is refused, because \"?\" means the expression was written where Sunday is 1. Refused: Quartz L, Quartz W, Quartz #, six fields (seconds), seven fields (year), @reboot, @every, CRON_TZ= prefixes, time zones of any kind — each with a code saying what to send instead."
},
"name": {
"type": "string",
"description": "Your name for the task. Unique among your live tasks; creating with an existing name updates it."
},
"method": {
"type": "string",
"description": "HTTP method of the delivery. Default POST. GET and HEAD carry no body."
},
"headers": {
"type": "object",
"description": "Headers we send with the delivery. Stored ENCRYPTED at rest — put credentials here, never in the body."
},
"timeoutMs": {
"type": "integer",
"description": "How long we wait for your server, 250-2000 ms. Answer 202 and do the work behind it."
}
},
"additionalProperties": false
}Remove a claimed URL. Refused while a task still points at it — delete the task first.
| Argument | Type | Description |
|---|---|---|
| id* | integer | Destination id, as returned by register_destination. |
{
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "integer",
"description": "Destination id, as returned by register_destination."
}
},
"additionalProperties": false
}Move the task to the recycle bin. It stops firing immediately and can be restored for 30 days with restore_task; after that it is unrecoverable. Credits already spent are not refunded.
| Argument | Type | Description |
|---|---|---|
| id* | string | Task id (UUID), as returned by create_task or list_tasks. |
{
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "Task id (UUID), as returned by create_task or list_tasks."
}
},
"additionalProperties": false
}One section of the machine documentation: quickstart, headers, signature, notice, errors, billing or limits. Omit `section` to get the whole document.
| Argument | Type | Description |
|---|---|---|
| section | string | Which section to return. Omit for all of it. |
{
"type": "object",
"properties": {
"section": {
"enum": [
"quickstart",
"verification",
"headers",
"signature",
"notice",
"errors",
"billing",
"limits"
],
"type": "string",
"description": "Which section to return. Omit for all of it."
}
},
"additionalProperties": false
}What a delivery costs, which packs exist, and the exact x402 payment requirements for each. Balance is counted in DELIVERIES, not money, and packs never expire. Call this before buying.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}Whether the service is currently selling, on which network, and if not — why not. This is configuration, not liveness: the full health endpoint is at /health.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}A single task: schedule, destination, state, next run, and how many failures in a row it carries.
| Argument | Type | Description |
|---|---|---|
| id* | string | Task id (UUID), as returned by create_task or list_tasks. |
{
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "Task id (UUID), as returned by create_task or list_tasks."
}
},
"additionalProperties": false
}The URLs you have claimed and whether each is verified. The signing secrets are never shown again.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}Your tasks and their state. Needs your management token as an Authorization header on this connection.
| Argument | Type | Description |
|---|---|---|
| after | string | Cursor from a previous page. |
| limit | integer | How many to return. |
| state | string | Filter by state: live (default), all, or one exact state such as active or paused_by_client. |
{
"type": "object",
"properties": {
"after": {
"type": "string",
"description": "Cursor from a previous page."
},
"limit": {
"type": "integer",
"description": "How many to return."
},
"state": {
"type": "string",
"description": "Filter by state: live (default), all, or one exact state such as active or paused_by_client."
}
},
"additionalProperties": false
}Stop firing until you resume. Nothing is charged while a task is paused.
| Argument | Type | Description |
|---|---|---|
| id* | string | Task id (UUID), as returned by create_task or list_tasks. |
{
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "Task id (UUID), as returned by create_task or list_tasks."
}
},
"additionalProperties": false
}Claim an https:// URL you control. We answer with a challenge and a SIGNING SECRET that is shown ONCE and never again — store it before you do anything else; it is what lets you verify that a delivery really came from us. The permission covers that path and everything beneath it, nothing above. Verification is one request from us to the exact URL you registered: POST, headers X-402cron-Challenge: <value> and X-402cron-Event: verify, JSON body {"challenge":"<value>"}. Reply within 5 seconds, without a redirect, with a body that is the bare value or {"challenge":"<value>"}; we read the first 512 bytes and do not check the HTTP status (2xx is fine). Then call POST /api/destinations/{id}/verify within 15 minutes of registering. A fixed-response webhook cannot pass: you need an endpoint you can program. Registering a URL that is still pending issues a new challenge and a new signing secret every time — the old secret immediately stops verifying deliveries; a verified URL is left untouched unless you add ?rotate=1. The daily verification allowance (10 per destination, 40 per client, UTC day) does not reset on re-registration.
| Argument | Type | Description |
|---|---|---|
| url* | string | The https:// URL you control. |
{
"type": "object",
"required": [
"url"
],
"properties": {
"url": {
"type": "string",
"description": "The https:// URL you control."
}
},
"additionalProperties": false
}Bring a task back from the recycle bin within 30 days. It comes back PAUSED — resume it explicitly.
| Argument | Type | Description |
|---|---|---|
| id* | string | Task id (UUID), as returned by create_task or list_tasks. |
{
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "Task id (UUID), as returned by create_task or list_tasks."
}
},
"additionalProperties": false
}Start firing again on the schedule. Refused if your balance is empty — buy deliveries first.
| Argument | Type | Description |
|---|---|---|
| id* | string | Task id (UUID), as returned by create_task or list_tasks. |
{
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "Task id (UUID), as returned by create_task or list_tasks."
}
},
"additionalProperties": false
}Deliver immediately, outside the schedule. THIS COSTS ONE CREDIT per attempt, exactly like a scheduled firing, and a timeout or unreachable host is retried up to three times — so one call can cost up to three credits. Use it to test a destination.
| Argument | Type | Description |
|---|---|---|
| id* | string | Task id (UUID), as returned by create_task or list_tasks. |
{
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "Task id (UUID), as returned by create_task or list_tasks."
}
},
"additionalProperties": false
}Change the schedule, destination, method, timeout, headers or body of an existing task. Omit a field to leave it unchanged — sending null is refused, because "unchanged" and "cleared" must not look the same. State is NOT editable here: use pause_task and resume_task.
| Argument | Type | Description |
|---|---|---|
| id* | string | Task id (UUID), as returned by create_task or list_tasks. |
| url | string | The https:// destination. It must already be registered and verified — see register_destination. |
| body | any | The body we send. Stored in the clear, so it must not carry credentials. A non-string is serialized as JSON. |
| cron | string | 5 fields, UTC only, one minute at the finest. Operators: * a-b a,b */n a-b/n. Names: SUN-SAT (day), JAN-DEC (month). Macros: @yearly @annually @monthly @weekly @daily @midnight @hourly. Day-of-week is 0-6 with 0 = Sunday; 7 also means Sunday. Write days as names (MON-FRI). Numbers differ between schedulers: Quartz, AWS EventBridge and Cloudflare number Sunday as 1, we and croniter as 0. Translated for you: "?". "?" as a whole day-of-month or day-of-week field becomes "*". A NUMERIC day-of-week next to "?" is refused, because "?" means the expression was written where Sunday is 1. Refused: Quartz L, Quartz W, Quartz #, six fields (seconds), seven fields (year), @reboot, @every, CRON_TZ= prefixes, time zones of any kind — each with a code saying what to send instead. |
| name | string | Your name for the task. Unique among your live tasks; creating with an existing name updates it. |
Verification is one request from us to the exact URL you registered: POST, headers X-402cron-Challenge: <value> and X-402cron-Event: verify, JSON body {"challenge":"<value>"}. Reply within 5 seconds, without a redirect, with a body that is the bare value or {"challenge":"<value>"}; we read the first 512 bytes and do not check the HTTP status (2xx is fine). Then call POST /api/destinations/{id}/verify within 15 minutes of registering. A fixed-response webhook cannot pass: you need an endpoint you can program. Registering a URL that is still pending issues a new challenge and a new signing secret every time — the old secret immediately stops verifying deliveries; a verified URL is left untouched unless you add ?rotate=1. The daily verification allowance (10 per destination, 40 per client, UTC day) does not reset on re-registration. Until this passes, no task may point at the destination.
| Argument | Type | Description |
|---|---|---|
| id* | integer | Destination id, as returned by register_destination. |
{
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "integer",
"description": "Destination id, as returned by register_destination."
}
},
"additionalProperties": false
}| method | string | HTTP method of the delivery. Default POST. GET and HEAD carry no body. |
| headers | object | Headers we send with the delivery. Stored ENCRYPTED at rest — put credentials here, never in the body. |
| timeoutMs | integer | How long we wait for your server, 250-2000 ms. Answer 202 and do the work behind it. |
{
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "Task id (UUID), as returned by create_task or list_tasks."
},
"url": {
"type": "string",
"description": "The https:// destination. It must already be registered and verified — see register_destination."
},
"body": {
"description": "The body we send. Stored in the clear, so it must not carry credentials. A non-string is serialized as JSON."
},
"cron": {
"type": "string",
"description": "5 fields, UTC only, one minute at the finest. Operators: * a-b a,b */n a-b/n. Names: SUN-SAT (day), JAN-DEC (month). Macros: @yearly @annually @monthly @weekly @daily @midnight @hourly. Day-of-week is 0-6 with 0 = Sunday; 7 also means Sunday. Write days as names (MON-FRI). Numbers differ between schedulers: Quartz, AWS EventBridge and Cloudflare number Sunday as 1, we and croniter as 0. Translated for you: \"?\". \"?\" as a whole day-of-month or day-of-week field becomes \"*\". A NUMERIC day-of-week next to \"?\" is refused, because \"?\" means the expression was written where Sunday is 1. Refused: Quartz L, Quartz W, Quartz #, six fields (seconds), seven fields (year), @reboot, @every, CRON_TZ= prefixes, time zones of any kind — each with a code saying what to send instead."
},
"name": {
"type": "string",
"description": "Your name for the task. Unique among your live tasks; creating with an existing name updates it."
},
"method": {
"type": "string",
"description": "HTTP method of the delivery. Default POST. GET and HEAD carry no body."
},
"headers": {
"type": "object",
"description": "Headers we send with the delivery. Stored ENCRYPTED at rest — put credentials here, never in the body."
},
"timeoutMs": {
"type": "integer",
"description": "How long we wait for your server, 250-2000 ms. Answer 202 and do the work behind it."
}
},
"additionalProperties": false
}