Triggers
Run a job by hand, on a schedule, from a token, or from the CLI, and get told when it finishes.
A job can start four ways. All of them produce the same kind of run.
By hand
Run now on the job page, or aq job run <job>.
On a schedule
A cron expression, always interpreted in UTC. The console previews the next five firings in both your timezone and UTC, so you can see which you are choosing.
Why UTC and not your timezone
A cron in a shifting local timezone silently moves by an hour twice a year. A nightly job that runs at 03:00 except on two nights is the kind of bug nobody attributes to the scheduler.
If the job is already at its machine limit when a firing comes due, the run is queued rather than skipped. Work you scheduled is not silently dropped; it waits, and the placement deadline is what eventually gives up out loud.
If a schedule cannot be parsed, we stop firing it and say so on the job, rather than leaving it looking scheduled while nothing happens.
From a token
Mint a token on the job, then:
curl -X POST https://server.aquanode.io/api/v1/run/<job-id> \
-H "x-job-token: aq_job_..." \
-H "content-type: application/json" \
-d '{"inputs": {"prompt": "a cat"}}'A token's entire vocabulary is "start a run of this one job and read it back". It can reach nothing else on your account, which is what makes handing one to someone else safe.
Every token carries a rate limit and a run cap, both required at mint time. They defend against different things (hammering, and a slow bleed), and a token without both is how an account gets drained.
Webhooks
Give the job a URL and we POST the run and every one of its attempts when it reaches a
final state, so a run that moved between providers shows you that it did.
The body is signed as X-Aquanode-Signature: sha256=<hex>, an HMAC-SHA256 over the
exact bytes we sent. Verify against the raw body, not a re-encoded version of it, or your
digest will differ from ours.
The signing secret is shown once: the console shows it right after you create the job,
and POST /jobs returns it as a top-level webhookSecret on that one response. It is
minted the moment a job first gets a webhookUrl, so a PATCH that adds one to an
existing job returns it the same way. Nothing hands it back afterwards -- it is absent
from every GET, by design. If you lose it, clear the job's webhookUrl and set it
again, which mints a new secret and stops your old one verifying.
Delivery is attempted three times with backoff, and the outcome is stored on the run as one of three states:
| Value | Meaning |
|---|---|
delivered | Your endpoint returned a 2xx |
failed | Three attempts, none accepted |
not_configured | The job has no webhook, so we never tried |
not_configured is kept distinct from failed on purpose: "we never tried" and "we
tried and could not" are different facts, and collapsing them hides a broken integration
until someone goes looking.