Webhooks

A webhook URL is a private address that counts a finished item each time it's called. Anything that can call a URL can use it: a CI job, an automation service, a phone shortcut.

Create a webhook URL

  1. Sign in to the game.
  2. Open Account > Finished items > Webhooks and create one. You can have up to 5.
  3. Copy it straight away: it's shown once. It looks like this:
    https://ironvaleidle.com/api/hook/3f2b8c1e-7a4d-4e09-9b6f-0c5d2e8a1f47

Treat the URL like a password: anyone who has it can send items for you. If it leaks, regenerate it (the old one stops working) or delete it.

Calling it

Use GET or POST. With no parameters at all, a call counts one finished item of type item, with the webhook's label as its source. These optional fields describe it better. They go in the URL as query parameters only: a request body is never read for them, so a source or id inside a JSON or form body is ignored.

FieldMeaning
sourceThe tool, such as github or shortcuts. Defaults to the webhook's label
typeWhat was finished, such as pr_merged or task_completed (it sets the weight). Defaults to item
idThe tool's own id for the item, so a repeat counts once
atWhen it was finished: ISO 8601 or Unix seconds. Defaults to now
nHow many items this call stands for, 1 to 20. Defaults to 1

Repeats count once. If there's no id in the URL, Ironvale uses the delivery header the sender adds (Idempotency-Key, Webhook-Id, X-GitHub-Delivery, X-Gitlab-Event-UUID, Linear-Delivery, X-Atlassian-Webhook-Identifier or X-Request-Id) or else a hash of the method, the URL and the first 16 KB of the body. Identical requests within 10 minutes count once, so a retried delivery isn't counted twice, while tools like Zapier or IFTTT that send a different body for each event are counted separately. Anything past the first 16 KB of a body is never read.

Nothing else is kept. The body is not parsed or stored, and the headers and URL are not stored. Only the same four things as every finished item are stored: source, a hashed id, type and time.

GitHub's setup ping (the event it sends when you add a webhook) is acknowledged and ignored.

Responses

StatusMeaning
202Received. The body says what happened: { "accepted": 1, "duplicate": 0, "ignored": 0 }, plus a reason when items were ignored. Items already counted show as duplicate; items over a limit are acknowledged and ignored (so senders don't retry)
400A URL field is malformed. The code is bad_source, bad_type, bad_id, bad_at or bad_n, or reserved_source for source=github.com (the built-in GitHub connection's)
404No such webhook: it was deleted or regenerated
413The request declares a body over 1 MB

The reason on an ignored item is one of: ping, daily_request_limit, rate_limited, daily_limit, too_many_sources, too_old or in_future.

Limits

Examples

Replace <your-hook> with your webhook's id.

curl

curl -X POST "https://ironvaleidle.com/api/hook/<your-hook>?source=cli&type=task_completed&id=release-2026-10-29"

GitHub

A plain repository webhook fires for every pull request event (opened, edited, closed), so each would count. To count only merges, use a small Actions workflow and keep the URL in a repository secret named IRONVALE_HOOK:

# .github/workflows/ironvale.yml
on:
  pull_request:
    types: [closed]
jobs:
  ironvale:
    if: github.event.pull_request.merged
    runs-on: ubuntu-latest
    steps:
      - run: curl -fsS -X POST "$HOOK?source=github&type=pr_merged&id=${{ github.event.pull_request.node_id }}"
        env:
          HOOK: ${{ secrets.IRONVALE_HOOK }}

For events that only happen when work is done, such as Releases, a repository webhook works directly: under Settings > Webhooks, set the payload URL to https://ironvaleidle.com/api/hook/<your-hook>?source=github&type=deploy and pick only that event. The X-GitHub-Delivery header keeps redeliveries from counting twice.

GitLab

A CI job on your default branch counts each merge:

# .gitlab-ci.yml
ironvale:
  stage: .post
  rules:
    - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  script:
    - curl -fsS -X POST "$IRONVALE_HOOK?source=gitlab&type=pr_merged&id=$CI_COMMIT_SHA"

Store the URL as a masked CI/CD variable named IRONVALE_HOOK. For a project webhook (Settings > Webhooks), choose an event that means finished, such as Releases events; the X-Gitlab-Event-UUID header de-duplicates retries.

Zapier

Trigger on whatever means done in your app (a task completed, a card moved to Done). Add the action Webhooks by Zapier > POST, put the fields in the URL: https://ironvaleidle.com/api/hook/<your-hook>?source=todoist&type=task_completed&id= followed by the task's id from the trigger.

IFTTT

Use the Webhooks service's Make a web request action, method POST, with the fields in the URL:

https://ironvaleidle.com/api/hook/<your-hook>?source=ifttt&type=task_completed

iOS and macOS Shortcuts

Make a shortcut called "Done for today" with one action, Get Contents of URL: method POST, URL https://ironvaleidle.com/api/hook/<your-hook>?source=shortcuts&type=task_completed&n=3. Change n to however many things you finished, up to 20. Without an id, two identical requests in a row look like a repeat, so add something unique such as the date and time (&id= followed by the Current Date variable).