{"openapi":"3.1.0","info":{"title":"agent-cronjob","version":"0.0.1","summary":"Agent-to-agent scheduled triggers: signed, retried, logged.","description":"Register a webhook, prove control with a challenge, receive an HMAC secret and a management token once, then get triggered on schedule. Full guide: https://cronjob.agentasy.ai/llms.txt (signature: https://cronjob.agentasy.ai/llms.txt#signature). Cron timezone defaults to UTC. The same operations are available as MCP tools at https://cronjob.agentasy.ai/mcp (Streamable HTTP, stateless; discovery https://cronjob.agentasy.ai/.well-known/mcp).","termsOfService":"https://cronjob.agentasy.ai/terms","contact":{"name":"agentasy.ai","email":"hello@agentasy.ai"}},"components":{"securitySchemes":{"managementToken":{"type":"http","scheme":"bearer","bearerFormat":"act_mt_…","description":"Issued once after verification."},"setupToken":{"type":"http","scheme":"bearer","bearerFormat":"act_st_…","description":"Returned by job creation; only for the verification endpoints."}},"schemas":{"Error":{"type":"object","description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","required":["error","message"],"additionalProperties":true,"properties":{"error":{"type":"string","examples":["invalid_request"]},"message":{"type":"string"}}},"IssuedCredentials":{"type":"object","description":"Returned once: by POST /v1/jobs/{id}/verify (callback mode) or by the first GET …/verification after echo verification.","additionalProperties":false,"required":["job_id","status","hmac_secret","management_token","next_run_at","signature","signature_spec_url","notice"],"properties":{"job_id":{"type":"string"},"status":{"type":"string"},"hmac_secret":{"type":"string","description":"acs_… HMAC-SHA256 key (use the string as UTF-8 bytes). Shown once."},"management_token":{"type":"string","description":"act_mt_… Bearer token for the management API. Shown once."},"next_run_at":{"type":["null","string"],"description":"First scheduled trigger (ISO 8601, UTC)"},"signature":{"type":"object","additionalProperties":false,"required":["header","format","algorithm","signed_string"],"properties":{"header":{"type":"string"},"format":{"type":"string"},"algorithm":{"type":"string"},"signed_string":{"type":"string"}}},"body_signature":{"type":"object","additionalProperties":false,"required":["field","format","algorithm","signed_string"],"description":"Present only when the job has signature_in_body: true. How to verify cronjob_signature inside the trigger body.","properties":{"field":{"type":"string"},"format":{"type":"string"},"algorithm":{"type":"string"},"signed_string":{"type":"string"}}},"signature_spec_url":{"type":"string","description":"llms.txt#signature"},"notice":{"type":"string"}}},"CreatedJob":{"type":"object","additionalProperties":false,"required":["job_id","status","setup_token","verification","next_steps"],"properties":{"job_id":{"type":"string"},"status":{"type":"string","enum":["pending_verification"]},"setup_token":{"type":"string","description":"act_st_… Bearer token for GET …/verification and POST …/verification/retry. Shown once."},"verification":{"type":"object","additionalProperties":false,"required":["mode","status","expires_at","challenge_sent_to","job_url","verify_url","poll_url","retry_url"],"properties":{"mode":{"type":"string","enum":["echo","callback"]},"status":{"type":"string"},"expires_at":{"type":"string"},"challenge_sent_to":{"type":"string","description":"webhook host"},"job_url":{"type":"string"},"verify_url":{"type":"string"},"poll_url":{"type":"string"},"retry_url":{"type":"string"}}},"next_steps":{"type":"array","items":{"type":"string"}}}},"VerificationStatus":{"type":"object","description":"Verification state. When `verification.credentials` is `issued_in_this_response`, the credential fields (hmac_secret, management_token, …) are present — exactly once.","additionalProperties":false,"required":["job_id","status","verification"],"properties":{"job_id":{"type":"string"},"status":{"type":"string"},"verification":{"type":"object","additionalProperties":false,"required":["mode","status","verified_via","last_result","challenges_sent","retries_left","expires_at","verified_at","credentials","credentials_claim_by"],"properties":{"mode":{"type":"string","enum":["echo","callback"]},"status":{"type":"string","enum":["pending","verified","expired","failed"]},"verified_via":{"type":["null","string"]},"last_result":{"type":["null","string"],"description":"e.g. echo_ok, awaiting_callback, http_500, timeout, ssrf_blocked: …"},"challenges_sent":{"type":"integer"},"retries_left":{"type":"integer"},"expires_at":{"type":["null","string"]},"verified_at":{"type":["null","string"]},"credentials":{"type":"string","enum":["issued_in_this_response","already_issued","expired","not_yet_verified"]},"credentials_claim_by":{"type":["null","string"]}}},"hmac_secret":{"type":"string","description":"acs_… HMAC-SHA256 key (use the string as UTF-8 bytes). Shown once."},"management_token":{"type":"string","description":"act_mt_… Bearer token for the management API. Shown once."},"next_run_at":{"type":["null","string"],"description":"First scheduled trigger (ISO 8601, UTC)"},"signature":{"type":"object","additionalProperties":false,"required":["header","format","algorithm","signed_string"],"properties":{"header":{"type":"string"},"format":{"type":"string"},"algorithm":{"type":"string"},"signed_string":{"type":"string"}}},"body_signature":{"type":"object","additionalProperties":false,"required":["field","format","algorithm","signed_string"],"description":"Present only when the job has signature_in_body: true. How to verify cronjob_signature inside the trigger body.","properties":{"field":{"type":"string"},"format":{"type":"string"},"algorithm":{"type":"string"},"signed_string":{"type":"string"}}},"signature_spec_url":{"type":"string","description":"llms.txt#signature"},"notice":{"type":"string"}}},"RetryResult":{"type":"object","additionalProperties":false,"required":["job_id","verification"],"properties":{"job_id":{"type":"string"},"verification":{"type":"object","additionalProperties":false,"required":["status","challenges_sent","retries_left","expires_at"],"properties":{"status":{"type":"string"},"challenges_sent":{"type":"integer"},"retries_left":{"type":"integer"},"expires_at":{"type":["null","string"]}}}}},"Job":{"type":"object","additionalProperties":false,"required":["job_id","name","status","status_reason","webhook","schedule","payload","max_runs","run_count","next_run_at","catchup_policy","catchup_window_sec","retry_max_attempts","retry_base_sec","retry_max_backoff_sec","timeout_ms","consecutive_failures","created_at","updated_at","verified_at","outgoing_auth","signature_in_body","credentials"],"properties":{"job_id":{"type":"string"},"name":{"type":["null","string"]},"status":{"type":"string","enum":["pending_verification","active","paused","completed","disabled","deleted"]},"status_reason":{"type":["null","string"],"description":"e.g. webhook_gone_410, consecutive_failures, max_runs_reached"},"webhook":{"type":"object","additionalProperties":false,"required":["host","url_masked"],"properties":{"host":{"type":"string"},"url_masked":{"type":"string","description":"scheme://host/*** — the path is never returned"}}},"schedule":{"type":"object","additionalProperties":false,"description":"One of {cron, timezone} | {interval_sec} | {run_at}","properties":{"cron":{"type":"string"},"timezone":{"type":"string"},"interval_sec":{"type":"integer"},"run_at":{"type":["null","string"]}}},"payload":{"type":"object","additionalProperties":true},"max_runs":{"type":["null","integer"],"description":"null = unlimited. Raise it with PATCH /v1/jobs/{id} (must stay > run_count); raising it on a job completed with max_runs_reached reactivates the job."},"run_count":{"type":"integer"},"next_run_at":{"type":["null","string"]},"catchup_policy":{"type":"string","enum":["skip","run_once","run_all"]},"catchup_window_sec":{"type":"integer"},"retry_max_attempts":{"type":"integer"},"retry_base_sec":{"type":"integer"},"retry_max_backoff_sec":{"type":"integer"},"timeout_ms":{"type":"integer"},"consecutive_failures":{"type":"integer"},"created_at":{"type":["null","string"]},"updated_at":{"type":["null","string"]},"verified_at":{"type":["null","string"]},"outgoing_auth":{"type":["null","object"],"additionalProperties":false,"required":["header","configured"],"description":"null, or the configured outgoing auth header name. The value is write-only and never returned.","properties":{"header":{"type":"string"},"configured":{"type":"boolean","enum":[true]}}},"signature_in_body":{"type":"boolean","description":"true = every trigger body also carries cronjob_signature (for receivers that drop the X-Cronjob-* headers). Default false."},"credentials":{"type":"object","additionalProperties":false,"required":["hmac_secrets","management_tokens"],"properties":{"hmac_secrets":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["prefix","status","created_at","expires_at"],"properties":{"prefix":{"type":"string"},"status":{"type":"string","enum":["active","retiring"]},"created_at":{"type":["null","string"]},"expires_at":{"type":["null","string"]}}}},"management_tokens":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["prefix","status","created_at","expires_at"],"properties":{"prefix":{"type":"string"},"status":{"type":"string","enum":["active","retiring"]},"created_at":{"type":["null","string"]},"expires_at":{"type":["null","string"]}}}}}}}},"DeletedJob":{"type":"object","additionalProperties":false,"required":["job_id","status","status_reason","deleted_at"],"properties":{"job_id":{"type":"string"},"status":{"type":"string","enum":["deleted"]},"status_reason":{"type":["null","string"]},"deleted_at":{"type":["null","string"]}}},"RotatedSecret":{"type":"object","additionalProperties":false,"required":["job_id","hmac_secret","prefix","previous","notice"],"properties":{"job_id":{"type":"string"},"hmac_secret":{"type":"string","description":"New acs_… key. Shown once."},"prefix":{"type":"string"},"previous":{"type":["null","object"],"additionalProperties":false,"required":["prefix","status","expires_at"],"properties":{"prefix":{"type":"string"},"status":{"type":"string"},"expires_at":{"type":["null","string"]}}},"notice":{"type":"string"}}},"RotatedToken":{"type":"object","additionalProperties":false,"required":["job_id","management_token","prefix","previous","notice"],"properties":{"job_id":{"type":"string"},"management_token":{"type":"string","description":"New act_mt_… token. Shown once."},"prefix":{"type":"string"},"previous":{"type":["null","object"],"additionalProperties":false,"required":["prefix","status","expires_at"],"properties":{"prefix":{"type":"string"},"status":{"type":"string"},"expires_at":{"type":["null","string"]}}},"notice":{"type":"string"}}},"Run":{"type":"object","additionalProperties":false,"required":["run_id","run_number","delivery_id","kind","status","scheduled_at","first_sent_at","first_delay_ms","attempts","missed_count","final_at","final_reason","late_cause"],"properties":{"run_id":{"type":"string"},"run_number":{"type":"integer"},"delivery_id":{"type":"string","description":"Idempotency id (X-Cronjob-Delivery-Id); identical on every attempt of the run."},"kind":{"type":"string","enum":["scheduled","catchup"],"description":"catchup = stands in for runs missed during downtime"},"status":{"type":"string","enum":["pending","succeeded","failed","missed","superseded","cancelled"]},"scheduled_at":{"type":["null","string"]},"first_sent_at":{"type":["null","string"]},"first_delay_ms":{"type":["null","integer"],"description":"first_sent_at − scheduled_at"},"attempts":{"type":"integer"},"missed_count":{"type":"integer"},"final_at":{"type":["null","string"]},"final_reason":{"type":["null","string"]},"late_cause":{"type":["null","string"],"enum":["host_pause",null],"description":"Why it was late, when known: host_pause = the window between scheduled and sent overlaps a recorded host (VM) pause of the service box. null = on time, still pending, or no known cause."}}},"RunsPage":{"type":"object","additionalProperties":false,"required":["job_id","runs","next_cursor"],"properties":{"job_id":{"type":"string"},"runs":{"type":"array","items":{"$ref":"#/components/schemas/Run"}},"next_cursor":{"type":["null","string"],"description":"Pass as ?cursor= for the next (older) page; null on the last page."}}},"Delivery":{"type":"object","additionalProperties":false,"required":["attempt","scheduled_at","sent_at","delay_ms","duration_ms","status_code","outcome","error","response_excerpt","next_attempt_at","late_cause"],"properties":{"attempt":{"type":"integer"},"scheduled_at":{"type":["null","string"]},"sent_at":{"type":["null","string"]},"delay_ms":{"type":["null","integer"]},"duration_ms":{"type":["null","integer"]},"status_code":{"type":["null","integer"]},"outcome":{"type":"string","enum":["scheduled","in_flight","succeeded","retryable","failed","lost","cancelled"]},"error":{"type":["null","string"]},"response_excerpt":{"type":["null","string"],"description":"First 1 KB of your response body"},"next_attempt_at":{"type":["null","string"]},"late_cause":{"type":["null","string"],"enum":["host_pause",null],"description":"Why it was late, when known: host_pause = the window between scheduled and sent overlaps a recorded host (VM) pause of the service box. null = on time, still pending, or no known cause."}}},"RunDetail":{"type":"object","additionalProperties":false,"required":["job_id","run_id","run_number","delivery_id","kind","status","scheduled_at","first_sent_at","first_delay_ms","attempts","missed_count","final_at","final_reason","late_cause","deliveries"],"properties":{"job_id":{"type":"string"},"run_id":{"type":"string"},"run_number":{"type":"integer"},"delivery_id":{"type":"string","description":"Idempotency id (X-Cronjob-Delivery-Id); identical on every attempt of the run."},"kind":{"type":"string","enum":["scheduled","catchup"],"description":"catchup = stands in for runs missed during downtime"},"status":{"type":"string","enum":["pending","succeeded","failed","missed","superseded","cancelled"]},"scheduled_at":{"type":["null","string"]},"first_sent_at":{"type":["null","string"]},"first_delay_ms":{"type":["null","integer"],"description":"first_sent_at − scheduled_at"},"attempts":{"type":"integer"},"missed_count":{"type":"integer"},"final_at":{"type":["null","string"]},"final_reason":{"type":["null","string"]},"late_cause":{"type":["null","string"],"enum":["host_pause",null],"description":"Why it was late, when known: host_pause = the window between scheduled and sent overlaps a recorded host (VM) pause of the service box. null = on time, still pending, or no known cause."},"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/Delivery"}}}},"Stats":{"type":"object","additionalProperties":false,"required":["job_id","window","from","to","runs","by_status","success_rate","on_time_rate","on_time_threshold_ms","first_delay_ms","late"],"properties":{"job_id":{"type":"string"},"window":{"type":"string","enum":["1h","24h","7d","30d"]},"from":{"type":"string"},"to":{"type":"string"},"runs":{"type":"integer"},"by_status":{"type":"object","additionalProperties":false,"required":["pending","succeeded","failed","missed","superseded","cancelled"],"properties":{"pending":{"type":"integer"},"succeeded":{"type":"integer"},"failed":{"type":"integer"},"missed":{"type":"integer"},"superseded":{"type":"integer"},"cancelled":{"type":"integer"}}},"success_rate":{"type":["null","number"],"description":"succeeded / (succeeded + failed + superseded)"},"on_time_rate":{"type":["null","number"],"description":"share of sent runs whose first attempt left within on_time_threshold_ms"},"on_time_threshold_ms":{"type":"integer"},"first_delay_ms":{"type":"object","additionalProperties":false,"required":["p50","p95","max","samples"],"properties":{"p50":{"type":["null","integer"]},"p95":{"type":["null","integer"]},"max":{"type":["null","integer"]},"samples":{"type":"integer"}}},"late":{"type":"object","additionalProperties":false,"required":["count","host_pause","missed_host_pause"],"description":"Late runs by cause. count: sent later than on_time_threshold_ms; host_pause: of those, overlapping a recorded host (VM) pause of the service; missed_host_pause: missed occurrences overlapping one.","properties":{"count":{"type":"integer"},"host_pause":{"type":"integer"},"missed_host_pause":{"type":"integer"}}}}},"UrlVerification":{"type":"object","additionalProperties":false,"required":["type","job_id","challenge","verify_url"],"properties":{"type":{"type":"string","enum":["url_verification"]},"job_id":{"type":"string"},"challenge":{"type":"string","description":"Random value. Echo it back (echo mode) or POST it to verify_url (callback mode)."},"verify_url":{"type":"string"}}},"Trigger":{"type":"object","additionalProperties":false,"required":["type","job_id","delivery_id","attempt","scheduled_at","sent_at","run_number","payload"],"properties":{"type":{"type":"string","enum":["trigger"]},"job_id":{"type":"string"},"delivery_id":{"type":"string","description":"Idempotency id; the same on every retry of this run. De-duplicate on it."},"attempt":{"type":"integer","minimum":1},"scheduled_at":{"type":"string"},"sent_at":{"type":"string"},"run_number":{"type":"integer"},"catchup":{"type":"boolean","description":"Present (true) when this run stands in for runs missed during downtime (catchup_policy run_once)."},"missed_count":{"type":"integer","description":"With catchup: how many missed points this run merges."},"payload":{"type":"object","additionalProperties":true,"description":"The payload you set on the job, unchanged."},"cronjob_signature":{"type":"object","additionalProperties":false,"required":["version","timestamp","delivery_id","signatures","signature"],"description":"Only when the job has signature_in_body: true. Each signature = hex HMAC-SHA256(hmac_secret, \"v1b:{timestamp}:{delivery_id}:\" + canonical JSON of this body without cronjob_signature) — canonical JSON = object keys sorted recursively, no whitespace, array order kept. Survives receivers that drop headers or re-serialize JSON. Reject if timestamp is more than 300 s off.","properties":{"version":{"type":"string","enum":["v1"]},"timestamp":{"type":"integer","description":"Unix seconds when this attempt was sent (same as X-Cronjob-Timestamp)."},"delivery_id":{"type":"string"},"signatures":{"type":"array","minItems":1,"items":{"type":"string"},"description":"One per active secret, newest first (two during a rotate-secret grace period)."},"signature":{"type":"string","description":"= signatures[0]"}}}}}}},"paths":{"/status":{"get":{"operationId":"getStatus","summary":"Public health: scheduler heartbeat, 1h/24h punctuality and schema version (aggregate values only, no job data).","tags":["service"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["service","version","status","degraded_reasons","time","uptime_sec","scheduler","host_pause","deliveries","db"],"properties":{"service":{"type":"string"},"version":{"type":"string"},"status":{"type":"string","enum":["ok","degraded"],"description":"degraded when the scheduler heartbeat is stale or last-hour deliveries are late (see degraded_reasons)."},"degraded_reasons":{"type":"array","items":{"type":"string","enum":["scheduler_stale","late_p95","late_last","missed"]},"description":"Empty when ok. scheduler_stale: heartbeat older than 30 s; late_p95: last_1h.first_delay_p95_ms above the threshold (default 30000); late_last: last_first_delay_ms above the threshold (default 30000) and sent within the last hour; missed: last_1h.missed_count above the allowed count (default 0)."},"time":{"type":"string"},"uptime_sec":{"type":"integer"},"scheduler":{"type":"object","additionalProperties":false,"required":["state","last_heartbeat_at","heartbeat_age_sec","max_tick_gap_sec_1h"],"properties":{"state":{"type":"string","enum":["not_started","ok","stale"]},"last_heartbeat_at":{"type":["null","string"]},"heartbeat_age_sec":{"type":["null","integer"]},"max_tick_gap_sec_1h":{"type":["null","integer"],"description":"Largest gap between two scheduler heartbeats in the last hour (ticks are 1 s apart), including restarts and pauses."}}},"host_pause":{"type":"object","additionalProperties":false,"description":"Pauses of the whole service box (VM snapshot/restore) seen by the scheduler as a tick far later than expected. Informational: they do not change status/degraded_reasons.","required":["last","count_1h","count_24h"],"properties":{"last":{"type":["null","object"],"additionalProperties":false,"required":["source","started_at","ended_at","duration_ms","age_sec"],"properties":{"source":{"type":"string","enum":["tick","dmesg","backfill"]},"started_at":{"type":["null","string"]},"ended_at":{"type":"string"},"duration_ms":{"type":["null","integer"]},"age_sec":{"type":"integer"}},"description":"Most recent recorded pause (any age); null if none."},"count_1h":{"type":"integer"},"count_24h":{"type":"integer"}}},"deliveries":{"type":"object","additionalProperties":false,"description":"Punctuality over all jobs: aggregate numbers only.","required":["on_time_threshold_ms","last_first_delay_ms","last_1h","last_24h"],"properties":{"on_time_threshold_ms":{"type":"integer"},"last_first_delay_ms":{"type":["null","integer"],"description":"First-attempt delay of the most recently sent trigger (any job, last 24 h); null if none."},"last_1h":{"type":"object","additionalProperties":false,"required":["runs","sent","missed_count","on_time_rate","success_rate","first_delay_p50_ms","first_delay_p95_ms","late_count","late_host_pause_count","missed_host_pause_count"],"properties":{"runs":{"type":"integer","description":"Runs scheduled in the window (all jobs, any status)."},"sent":{"type":"integer","description":"Runs whose first attempt went out (delay samples)."},"missed_count":{"type":"integer","description":"Occurrences in the window recorded as missed (the scheduler was too late; see catch-up)."},"on_time_rate":{"type":["null","number"],"description":"Share of sent runs whose first attempt left within on_time_threshold_ms."},"success_rate":{"type":["null","number"],"description":"succeeded / (succeeded + failed + superseded)."},"first_delay_p50_ms":{"type":["null","integer"]},"first_delay_p95_ms":{"type":["null","integer"]},"late_count":{"type":"integer","description":"Sent runs whose first attempt left later than on_time_threshold_ms."},"late_host_pause_count":{"type":"integer","description":"Of late_count, runs whose lateness overlaps a recorded host (VM) pause (late_cause host_pause)."},"missed_host_pause_count":{"type":"integer","description":"Of missed_count, occurrences overlapping a recorded host pause."}}},"last_24h":{"type":"object","additionalProperties":false,"required":["runs","sent","missed_count","on_time_rate","success_rate","first_delay_p50_ms","first_delay_p95_ms","late_count","late_host_pause_count","missed_host_pause_count"],"properties":{"runs":{"type":"integer","description":"Runs scheduled in the window (all jobs, any status)."},"sent":{"type":"integer","description":"Runs whose first attempt went out (delay samples)."},"missed_count":{"type":"integer","description":"Occurrences in the window recorded as missed (the scheduler was too late; see catch-up)."},"on_time_rate":{"type":["null","number"],"description":"Share of sent runs whose first attempt left within on_time_threshold_ms."},"success_rate":{"type":["null","number"],"description":"succeeded / (succeeded + failed + superseded)."},"first_delay_p50_ms":{"type":["null","integer"]},"first_delay_p95_ms":{"type":["null","integer"]},"late_count":{"type":"integer","description":"Sent runs whose first attempt left later than on_time_threshold_ms."},"late_host_pause_count":{"type":"integer","description":"Of late_count, runs whose lateness overlaps a recorded host (VM) pause (late_cause host_pause)."},"missed_host_pause_count":{"type":"integer","description":"Of missed_count, occurrences overlapping a recorded host pause."}}}}},"db":{"type":"object","additionalProperties":false,"required":["schema_version"],"properties":{"schema_version":{"type":"integer"}}}}}}}}}}},"/v1/jobs":{"post":{"operationId":"createJob","summary":"Create a job (no auth). A url_verification challenge is then POSTed to webhook_url.","tags":["registration"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["webhook_url","schedule"],"description":"Unknown fields are rejected (400) so typos surface immediately.","properties":{"webhook_url":{"type":"string","minLength":1,"maxLength":2048,"description":"https URL on a public address. Private/loopback/link-local/metadata addresses are refused; redirects are never followed."},"name":{"type":["string","null"],"maxLength":200},"schedule":{"type":"object","additionalProperties":false,"description":"Exactly one of: {cron, timezone?} (5-field cron or @hourly/@daily/…; timezone is IANA and defaults to UTC), {interval_sec}, or {run_at} (ISO 8601 with Z or an offset, in the future). Minimum spacing 60 s.","examples":[{"cron":"*/15 * * * *","timezone":"Asia/Taipei"},{"interval_sec":3600},{"run_at":"2030-01-01T00:00:00Z"}],"properties":{"cron":{"type":"string","minLength":1,"maxLength":200},"timezone":{"type":"string","minLength":1,"maxLength":64,"description":"IANA zone for cron. Default UTC."},"interval_sec":{"type":"integer","description":"60 … 31622400"},"run_at":{"type":"string","minLength":1,"maxLength":64}}},"payload":{"type":"object","description":"Sent unchanged in every trigger (≤ 8 KB)."},"max_runs":{"type":["integer","null"],"description":"Job completes after this many dispatched runs (1 … 1000000); null = unlimited."},"catchup_policy":{"type":"string","enum":["skip","run_once","run_all"],"description":"What happens to runs missed during service downtime. Default run_once."},"catchup_window_sec":{"type":"integer","description":"Missed runs older than this are only logged as missed (0 … 604800). Default 3600."},"retry_max_attempts":{"type":"integer","description":"Attempts per run including the first (1 … 10). Default 5."},"retry_base_sec":{"type":"integer","description":"Backoff base: base × 2^(attempt−1) × jitter 0.8–1.2 (1 … 3600). Default 30."},"retry_max_backoff_sec":{"type":"integer","description":"Backoff cap (≤ 86400). Default 3600."},"timeout_ms":{"type":"integer","description":"Per-request timeout (1000 … 30000). Default 10000."},"verification_mode":{"type":"string","enum":["echo","callback"],"description":"Informational; either mode completes the challenge. Default echo."},"outgoing_auth":{"type":["object","null"],"additionalProperties":false,"required":["value"],"description":"Optional header your webhook requires (e.g. a Grok routine webhook needing Authorization: Bearer …). Sent on the url_verification POST and on every trigger; never overrides the X-Cronjob-* headers. The value is stored encrypted and never returned (job responses show only {header, configured: true}).","examples":[{"header":"Authorization","value":"Bearer <your webhook token>"}],"properties":{"header":{"type":"string","minLength":1,"maxLength":64,"default":"Authorization","description":"Authorization (default) or an X-… header name (not X-Cronjob-…). Case-insensitive."},"value":{"type":"string","minLength":1,"maxLength":4096,"description":"Header value, 1 … 4096 characters, no CR/LF or other control characters. Secret: write-only."}}},"signature_in_body":{"type":"boolean","default":false,"description":"Default false. true = every trigger body also carries a top-level cronjob_signature object {version, timestamp, delivery_id, signatures[], signature}: HMAC-SHA256(hmac_secret, \"v1b:{timestamp}:{delivery_id}:\" + canonical JSON of the body without cronjob_signature). For receivers that drop the X-Cronjob-* headers or re-serialize the JSON (e.g. Grok Bot routines). The header signature is sent as well, unchanged."}}},"example":{"webhook_url":"https://your-agent.example/hooks/abc","schedule":{"cron":"0 * * * *","timezone":"UTC"},"payload":{"task":"hourly-digest"},"verification_mode":"echo"}}},"description":"Unknown fields are rejected (400) so typos surface immediately."},"security":[],"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedJob"}}}},"4XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"5XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/":{"post":{"operationId":"createJobViaEntryHost","summary":"Same as POST /v1/jobs, on the entry host (read GET / there, then POST to the same URL).","tags":["registration"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["webhook_url","schedule"],"description":"Unknown fields are rejected (400) so typos surface immediately.","properties":{"webhook_url":{"type":"string","minLength":1,"maxLength":2048,"description":"https URL on a public address. Private/loopback/link-local/metadata addresses are refused; redirects are never followed."},"name":{"type":["string","null"],"maxLength":200},"schedule":{"type":"object","additionalProperties":false,"description":"Exactly one of: {cron, timezone?} (5-field cron or @hourly/@daily/…; timezone is IANA and defaults to UTC), {interval_sec}, or {run_at} (ISO 8601 with Z or an offset, in the future). Minimum spacing 60 s.","examples":[{"cron":"*/15 * * * *","timezone":"Asia/Taipei"},{"interval_sec":3600},{"run_at":"2030-01-01T00:00:00Z"}],"properties":{"cron":{"type":"string","minLength":1,"maxLength":200},"timezone":{"type":"string","minLength":1,"maxLength":64,"description":"IANA zone for cron. Default UTC."},"interval_sec":{"type":"integer","description":"60 … 31622400"},"run_at":{"type":"string","minLength":1,"maxLength":64}}},"payload":{"type":"object","description":"Sent unchanged in every trigger (≤ 8 KB)."},"max_runs":{"type":["integer","null"],"description":"Job completes after this many dispatched runs (1 … 1000000); null = unlimited."},"catchup_policy":{"type":"string","enum":["skip","run_once","run_all"],"description":"What happens to runs missed during service downtime. Default run_once."},"catchup_window_sec":{"type":"integer","description":"Missed runs older than this are only logged as missed (0 … 604800). Default 3600."},"retry_max_attempts":{"type":"integer","description":"Attempts per run including the first (1 … 10). Default 5."},"retry_base_sec":{"type":"integer","description":"Backoff base: base × 2^(attempt−1) × jitter 0.8–1.2 (1 … 3600). Default 30."},"retry_max_backoff_sec":{"type":"integer","description":"Backoff cap (≤ 86400). Default 3600."},"timeout_ms":{"type":"integer","description":"Per-request timeout (1000 … 30000). Default 10000."},"verification_mode":{"type":"string","enum":["echo","callback"],"description":"Informational; either mode completes the challenge. Default echo."},"outgoing_auth":{"type":["object","null"],"additionalProperties":false,"required":["value"],"description":"Optional header your webhook requires (e.g. a Grok routine webhook needing Authorization: Bearer …). Sent on the url_verification POST and on every trigger; never overrides the X-Cronjob-* headers. The value is stored encrypted and never returned (job responses show only {header, configured: true}).","examples":[{"header":"Authorization","value":"Bearer <your webhook token>"}],"properties":{"header":{"type":"string","minLength":1,"maxLength":64,"default":"Authorization","description":"Authorization (default) or an X-… header name (not X-Cronjob-…). Case-insensitive."},"value":{"type":"string","minLength":1,"maxLength":4096,"description":"Header value, 1 … 4096 characters, no CR/LF or other control characters. Secret: write-only."}}},"signature_in_body":{"type":"boolean","default":false,"description":"Default false. true = every trigger body also carries a top-level cronjob_signature object {version, timestamp, delivery_id, signatures[], signature}: HMAC-SHA256(hmac_secret, \"v1b:{timestamp}:{delivery_id}:\" + canonical JSON of the body without cronjob_signature). For receivers that drop the X-Cronjob-* headers or re-serialize the JSON (e.g. Grok Bot routines). The header signature is sent as well, unchanged."}}},"example":{"webhook_url":"https://your-agent.example/hooks/abc","schedule":{"cron":"0 * * * *","timezone":"UTC"},"payload":{"task":"hourly-digest"},"verification_mode":"echo"}}},"description":"Unknown fields are rejected (400) so typos surface immediately."},"security":[],"servers":[{"url":"https://new-cronjob.agentasy.ai"}],"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedJob"}}}},"4XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"5XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/jobs/{id}/verify":{"post":{"operationId":"verifyChallenge","summary":"Callback verification: send back the challenge you received. The response holds your credentials (shown once).","tags":["registration"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["challenge"],"properties":{"challenge":{"type":"string","minLength":1,"maxLength":200}}}}}},"parameters":[{"schema":{"type":"string","pattern":"^job_[0-9A-HJKMNP-TV-Z]{26}$"},"in":"path","name":"id","required":true,"description":"job_<ULID>"}],"security":[],"responses":{"200":{"description":"Returned once: by POST /v1/jobs/{id}/verify (callback mode) or by the first GET …/verification after echo verification.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedCredentials"}}}},"4XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"5XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/jobs/{id}/verification":{"get":{"operationId":"getVerification","summary":"Poll verification state. After echo verification the first call returns hmac_secret and management_token (once).","tags":["registration"],"parameters":[{"schema":{"type":"string","pattern":"^job_[0-9A-HJKMNP-TV-Z]{26}$"},"in":"path","name":"id","required":true,"description":"job_<ULID>"}],"security":[{"setupToken":[]}],"responses":{"200":{"description":"Verification state. When `verification.credentials` is `issued_in_this_response`, the credential fields (hmac_secret, management_token, …) are present — exactly once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationStatus"}}}},"4XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"5XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/jobs/{id}/verification/retry":{"post":{"operationId":"retryVerification","summary":"Re-send a fresh challenge (at most 5 re-sends (6 challenges in total), at least 60 s apart). The previous challenge stops working.","tags":["registration"],"parameters":[{"schema":{"type":"string","pattern":"^job_[0-9A-HJKMNP-TV-Z]{26}$"},"in":"path","name":"id","required":true,"description":"job_<ULID>"}],"security":[{"setupToken":[]}],"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetryResult"}}}},"4XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"5XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/jobs/{id}":{"get":{"operationId":"getJob","summary":"Job settings, status and credential prefixes (the webhook path is masked).","tags":["jobs"],"parameters":[{"schema":{"type":"string","pattern":"^job_[0-9A-HJKMNP-TV-Z]{26}$"},"in":"path","name":"id","required":true,"description":"job_<ULID>"}],"security":[{"managementToken":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"4XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"5XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateJob","summary":"Change job settings in place: signature_in_body and/or max_runs (raising max_runs reactivates a job completed by max_runs_reached).","tags":["jobs"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"minProperties":1,"description":"Changeable in place: signature_in_body (from the next attempt sent) and max_runs. Other fields are rejected (400).","properties":{"signature_in_body":{"type":"boolean","description":"Default false. true = every trigger body also carries a top-level cronjob_signature object {version, timestamp, delivery_id, signatures[], signature}: HMAC-SHA256(hmac_secret, \"v1b:{timestamp}:{delivery_id}:\" + canonical JSON of the body without cronjob_signature). For receivers that drop the X-Cronjob-* headers or re-serialize the JSON (e.g. Grok Bot routines). The header signature is sent as well, unchanged."},"max_runs":{"type":["integer","null"],"description":"New run limit: integer 1 … 1000000 that must be greater than run_count, or null = unlimited. Lower or equal to run_count → 400. A job that is completed with status_reason max_runs_reached and gets a higher limit (or null) is reactivated implicitly: status active, status_reason cleared, next_run_at = next schedule occurrence after now (missed occurrences are not caught up). There is no separate resume for completed jobs. Paused / disabled jobs keep their status and just get the new limit. Completed for another reason, or a once job → 409."}}},"examples":{"example1":{"value":{"signature_in_body":true}},"example2":{"value":{"max_runs":20}}}}},"description":"Changeable in place: signature_in_body (from the next attempt sent) and max_runs. Other fields are rejected (400)."},"parameters":[{"schema":{"type":"string","pattern":"^job_[0-9A-HJKMNP-TV-Z]{26}$"},"in":"path","name":"id","required":true,"description":"job_<ULID>"}],"security":[{"managementToken":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"4XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"5XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteJob","summary":"Stop forever and revoke all credentials.","tags":["jobs"],"parameters":[{"schema":{"type":"string","pattern":"^job_[0-9A-HJKMNP-TV-Z]{26}$"},"in":"path","name":"id","required":true,"description":"job_<ULID>"}],"security":[{"managementToken":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedJob"}}}},"4XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"5XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/jobs/{id}/pause":{"post":{"operationId":"pauseJob","summary":"Stop triggering (idempotent). Points while paused are not made up later.","tags":["jobs"],"parameters":[{"schema":{"type":"string","pattern":"^job_[0-9A-HJKMNP-TV-Z]{26}$"},"in":"path","name":"id","required":true,"description":"job_<ULID>"}],"security":[{"managementToken":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"4XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"5XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/jobs/{id}/resume":{"post":{"operationId":"resumeJob","summary":"Resume a paused or disabled job from the next schedule point; resets consecutive_failures.","tags":["jobs"],"parameters":[{"schema":{"type":"string","pattern":"^job_[0-9A-HJKMNP-TV-Z]{26}$"},"in":"path","name":"id","required":true,"description":"job_<ULID>"}],"security":[{"managementToken":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"4XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"5XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/jobs/{id}/rotate-secret":{"post":{"operationId":"rotateSecret","summary":"New HMAC secret (shown once). Until previous.expires_at triggers carry two v1= signatures, new first.","tags":["credentials"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"anyOf":[{"type":"null"},{"type":"object","additionalProperties":false,"properties":{"grace_sec":{"type":"integer","minimum":0,"maximum":86400}}}]}}}},"parameters":[{"schema":{"type":"string","pattern":"^job_[0-9A-HJKMNP-TV-Z]{26}$"},"in":"path","name":"id","required":true,"description":"job_<ULID>"}],"security":[{"managementToken":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotatedSecret"}}}},"4XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"5XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/jobs/{id}/rotate-token":{"post":{"operationId":"rotateToken","summary":"New management token (shown once). The old one stops working after grace_sec (default 0).","tags":["credentials"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"anyOf":[{"type":"null"},{"type":"object","additionalProperties":false,"properties":{"grace_sec":{"type":"integer","minimum":0,"maximum":3600}}}]}}}},"parameters":[{"schema":{"type":"string","pattern":"^job_[0-9A-HJKMNP-TV-Z]{26}$"},"in":"path","name":"id","required":true,"description":"job_<ULID>"}],"security":[{"managementToken":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotatedToken"}}}},"4XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"5XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/jobs/{id}/runs":{"get":{"operationId":"listRuns","summary":"Trigger log, newest first. since/until filter scheduled_at.","tags":["runs"],"parameters":[{"schema":{"type":"string","maxLength":64},"in":"query","name":"since","required":false},{"schema":{"type":"string","maxLength":64},"in":"query","name":"until","required":false},{"schema":{"type":"string","enum":["pending","succeeded","failed","missed","superseded","cancelled"]},"in":"query","name":"status","required":false},{"schema":{"type":"integer","minimum":1,"maximum":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string","maxLength":64},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","pattern":"^job_[0-9A-HJKMNP-TV-Z]{26}$"},"in":"path","name":"id","required":true,"description":"job_<ULID>"}],"security":[{"managementToken":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunsPage"}}}},"4XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"5XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/jobs/{id}/runs/{run_id}":{"get":{"operationId":"getRun","summary":"One run with every delivery attempt.","tags":["runs"],"parameters":[{"schema":{"type":"string","pattern":"^job_[0-9A-HJKMNP-TV-Z]{26}$"},"in":"path","name":"id","required":true},{"schema":{"type":"string","pattern":"^run_[0-9A-HJKMNP-TV-Z]{26}$"},"in":"path","name":"run_id","required":true}],"security":[{"managementToken":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunDetail"}}}},"4XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"5XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/jobs/{id}/stats":{"get":{"operationId":"getStats","summary":"On-time rate, p50/p95 first-attempt delay and success rate over a window.","tags":["runs"],"parameters":[{"schema":{"type":"string","enum":["1h","24h","7d","30d"]},"in":"query","name":"window","required":false},{"schema":{"type":"string","pattern":"^job_[0-9A-HJKMNP-TV-Z]{26}$"},"in":"path","name":"id","required":true,"description":"job_<ULID>"}],"security":[{"managementToken":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Stats"}}}},"4XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"5XX":{"description":"Every error. `error` is a stable machine-readable code; extra fields (e.g. `field`, `limit`, `reason`) may be present. 429 responses carry a Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"servers":[{"url":"https://cronjob.agentasy.ai"}],"webhooks":{"urlVerification":{"post":{"summary":"Challenge sent to your webhook_url right after creation (not signed).","description":"Answer 2xx with {\"challenge\": \"<value>\"} (echo) or answer 2xx and POST the value to verify_url (callback). See https://cronjob.agentasy.ai/llms.txt","parameters":[{"name":"X-Cronjob-Event","in":"header","required":true,"description":"Always url_verification","schema":{"type":"string","examples":["url_verification"]}},{"name":"X-Cronjob-Job-Id","in":"header","required":true,"description":"job_<ULID>","schema":{"type":"string"}},{"name":"Authorization","in":"header","required":false,"description":"Only if the job was created with outgoing_auth: that header (Authorization by default, or the X-… name given) with the value you supplied. Never replaces the X-Cronjob-* headers.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UrlVerification"}}}},"responses":{"200":{"description":"echo mode: the same challenge value","content":{"application/json":{"schema":{"type":"object","required":["challenge"],"properties":{"challenge":{"type":"string"}}}},"text/plain":{"schema":{"type":"string"}}}},"default":{"description":"Any 2xx without the value = callback mode; anything else = not verified (retry later)."}}}},"trigger":{"post":{"summary":"Scheduled trigger sent to your webhook_url. Verify X-Cronjob-Signature, de-duplicate on delivery_id, reply 2xx.","description":"Signature: https://cronjob.agentasy.ai/llms.txt#signature. Retries: connection errors, timeouts, 5xx, 408, 429 (exponential backoff); other 4xx are final; 410 pauses the job.","parameters":[{"name":"X-Cronjob-Job-Id","in":"header","required":true,"description":"job_<ULID>","schema":{"type":"string"}},{"name":"X-Cronjob-Delivery-Id","in":"header","required":true,"description":"Idempotency id, identical on every attempt of the run","schema":{"type":"string","examples":["dlv_01JC0000000000000000000000"]}},{"name":"X-Cronjob-Attempt","in":"header","required":true,"description":"Attempt number, from 1","schema":{"type":"string","examples":["1"]}},{"name":"X-Cronjob-Scheduled-At","in":"header","required":true,"description":"Schedule point of this run (ISO 8601 UTC)","schema":{"type":"string"}},{"name":"X-Cronjob-Timestamp","in":"header","required":true,"description":"Unix seconds when this attempt was sent; reject if more than 300 s off","schema":{"type":"string","examples":["1793678400"]}},{"name":"X-Cronjob-Signature","in":"header","required":true,"description":"v1=<hex>[, v1=<hex>] — HMAC-SHA256(hmac_secret, \"v1:{timestamp}:{delivery_id}:{raw body}\")","schema":{"type":"string"}},{"name":"Authorization","in":"header","required":false,"description":"Only if the job was created with outgoing_auth: that header (Authorization by default, or the X-… name given) with the value you supplied. Never replaces the X-Cronjob-* headers.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Trigger"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the run."},"default":{"description":"408/429/5xx/timeouts are retried; other statuses are final; 410 pauses the job."}}}}},"tags":[{"name":"registration","description":"Create a job and prove webhook control"},{"name":"jobs","description":"Manage a job (Bearer management_token)"},{"name":"credentials","description":"Rotate the HMAC secret or management token"},{"name":"runs","description":"Trigger log and stats"},{"name":"service","description":"Service health"}],"externalDocs":{"description":"Agent guide (llms.txt)","url":"https://cronjob.agentasy.ai/llms.txt"}}