---
title: HTTP targets
description: A fire lands as a signed request to an https URL; a 2xx answer records success, anything else records a refusal.
type: how-to
product: jobs
summary: The receiver's side of a fire: what it is sent, what it answers, and what a refusal leaves behind.
updated: 2026-09-28
order: 1
---

On the surface that runs schedules today, a fire lands on an HTTP target: a
signed request to an https URL, in the method the target states, so the
receiver can tell a fire from anything else that knows the address. The declared `schedules` collection does not have
HTTP targets — its Schedule names the Workflow to start in the same
environment — so this page is about the Compute API's target.

## A target states four things

```bash
curl -X POST "https://api.compute.sylphx.com/v1/schedules" \
  -H "Authorization: Bearer $SYLPHX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"idempotencyKey":"targets-1","spec":{"calendar":{"kind":"rate","everySeconds":30,"timezone":"UTC"},"overlap":"skip","catchUp":"skip","target":{"kind":"http","method":"POST","url":"https://sylphx.com/unsubscribe/one-click","signed":true},"retry":{"maxAttempts":3},"pause":false}}'
```

<PropertyTable
	properties={[
		{
			name: 'target.kind',
			type: 'string',
			description: 'http: the fire is an HTTP request.',
		},
		{
			name: 'target.url',
			type: 'string',
			description: 'The address the fire is sent to. It must be https.',
		},
		{
			name: 'target.method',
			type: 'string',
			description: 'The method the fire uses.',
		},
		{
			name: 'target.signed',
			type: 'bool',
			description: 'Required, and it must be true: the request is signed.',
		},
		{
			name: 'retry.maxAttempts',
			type: 'uint64',
			description: 'How many times a fire is retried.',
		},
	]}
/>

`url` must be https and `signed` must be true. A target that is neither is
refused when the schedule is validated rather than when the first fire lands,
which is the difference between a create that fails in front of you and a
schedule that quietly never delivers. The signature is the receiver's check: a
fire arrives from the platform, and a request that merely knows the address is
not one.

## What the receiver answers

The receiver's whole job is a status. A 2xx answer records the tick as
`succeeded`. Anything else records it as `dead_lettered`, so a handler that
refuses — a payload it cannot use, a downstream that is down — leaves a dead
letter beside the tick rather than a fire that looks delivered.

Retries belong to the platform, bounded by `retry.maxAttempts`, so the handler
does not have to retry on its own. A handler that wants a fire retried should
answer with a refusal and let the platform do it, rather than holding the
request open.

## An easy first receiver

A receiver that answers 200 and ignores the body is enough to watch a schedule
fire end to end before you run one of your own. The run lines on this page and
on the [quickstart](/docs/jobs/quickstart) point at the public one-click route
(`https://sylphx.com/unsubscribe/one-click`), which answers 200 to any POST.

## Reading the outcome

`GET /v1/schedules/{id}` answers the schedule's own record, and both sides of
the fire are in it:

```bash
curl "https://api.compute.sylphx.com/v1/schedules/$SCHEDULE_ID" \
  -H "Authorization: Bearer $SYLPHX_API_KEY"
```

`lastTick` says what the most recent fire did, and `deadLetters` collects the
refusals. [Schedules](/docs/jobs/schedules) is what the tick states mean.

<RelatedDocs
	links={[
		{
			href: '/docs/jobs/schedules',
			label: 'Schedules',
			description: 'The tick states, catch-up, and the delete fence.',
		},
		{
			href: '/docs/jobs/quickstart',
			label: 'Quickstart',
			description: 'Create a schedule with an HTTP target, and read the fire back.',
		},
		{
			href: '/docs/api/schedules',
			label: 'The schedules collection',
			description: 'The Schedule Resource as declared, with every method and example.',
		},
	]}
/>
