verba volant, scripta manent

Challenges

Start challenges, list them, read one. Base URL, authentication and errors are in the introduction.

List challenges

GET/api/v1/challengesPublic

Filtered, sorted and paged in the database, 30 a page. Unknown values fall back to the defaults. Signed-out callers are metered per address (60/min).

Parameters

status"open" | "closed" | "all"query

open (default), closed or all.

categorystringquery

Topic ids, comma-separated: crypto, markets, sports, politics, tech, ai, science, business, culture, personal, other.

sort"soonest" | "newest" | "oldest" | "most" | "least"query

soonest (default: closing soonest while open, most recently closed once closed; open first with all), newest, oldest, most or least (by etches).

pageintegerquery

Page number, from 1. 30 a page.

Responses

  • 200A page of challenges.
  • 429Anonymous allowance exhausted for this address.
Request
curl https://test.etch.so/api/v1/challenges
Response
JSON
{
  "query": {
    "status": "all",
    "sort": "most",
    "categories": []
  },
  "challenges": [
    {
      "id": "022d7178-5d86-48f8-a4df-3036e1fe2c45",
      "question": "Fresh challenge 1792024128453-6313576",
      "category_id": "ai",
      "created_at": "2026-10-15T00:28:48.657Z",
      "reveal_at": "2026-10-15T01:28:48.453Z",
      "closed": true,
      "etch_count": 3,
      "participant_count": 3,
      "url": "https://test.etch.so/ch/022d7178-5d86-48f8-a4df-3036e1fe2c45"
    }
  ],
  "page": {
    "number": 1,
    "pages": 71,
    "total": 2113
  }
}

Start a challenge

POST/api/v1/challengesAPI key

A sealed challenge: the creator sets one reveal time, every etch inherits it, and etching ends when it passes. One etch per account, never an instant one.

Capped at 20 per account per day.

Parameters

Idempotency-Keystringheader

Makes a retry safe. Send the same key on a retry of the same request and you get the original record back with Idempotent-Replay: true, instead of a second permanent one.

Generate the key when you decide to write, and persist it BEFORE the first attempt — a fresh key per attempt protects against nothing. Reusing a key with a different body is refused with 409. Keys are kept for the life of the record and never expire.

questionstringbodyrequired

The question everyone etches on.

category_idstringbodyrequired

One topic id.

reveal_atstringbodyrequired

When the challenge closes: etching ends and every etch in it is revealed.

Responses

  • 201Started. Carries Idempotent-Replay: true when an Idempotency-Key matched an existing challenge.
  • 400Invalid body, or a reveal time too soon.
  • 409An Idempotency-Key reused for a different request.
  • 429Daily challenge allowance exhausted.
Request
curl -X POST https://test.etch.so/api/v1/challenges \
  -H "Authorization: Bearer $ETCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "Will the Fed cut rates at its December 2026 meeting?",
    "category_id": "markets",
    "reveal_at": "2026-12-17T19:00:00.000Z"
  }'
Response
JSON
{
  "challenge": {
    "id": "0398391e-afea-4eaf-874e-12de276d0a9f",
    "question": "Will the Fed cut rates at its December 2026 meeting?",
    "category": {
      "id": "markets",
      "label": "Markets"
    },
    "creator_id": "2d052485-adbf-4ce8-b47f-1af583c29183",
    "created_at": "2026-10-15T06:31:58.044Z",
    "reveal_at": "2026-12-29T06:31:57.758Z",
    "url": "https://test.etch.so/ch/0398391e-afea-4eaf-874e-12de276d0a9f"
  }
}

Read a challenge and its etches

GET/api/v1/challenges/{id}Public

The challenge, its counts, and a page of the etches made against it. While it is open those etches are sealed: who and which day, never what.

Parameters

idstringpathrequired

The challenge id (a UUID). The response also carries its six-character code and short_url, /ch/.

sort"newest" | "soonest"query

newest (default) or soonest.

limitintegerquery

Results per page, 1–100.

cursorstringquery

The next_cursor from the previous page.

Responses

  • 200The challenge.
  • 404No such challenge.
Request
curl https://test.etch.so/api/v1/challenges/$ID
Response
JSON
{
  "challenge": {
    "id": "022d7178-5d86-48f8-a4df-3036e1fe2c45",
    "code": "az4kp4",
    "short_url": "https://test.etch.so/ch/az4kp4",
    "question": "Fresh challenge 1792024128453-6313576",
    "category": {
      "id": "ai",
      "label": "AI"
    },
    "creator_id": "6342913f-a25f-4fc6-94b4-5e3756b966b4",
    "creator": {
      "username": "nova",
      "display_name": "fine",
      "x_handle": null,
      "x_verified_at": null,
      "official": false
    },
    "created_at": "2026-10-15T00:28:48.657Z",
    "reveal_at": "2026-10-15T01:28:48.453Z",
    "closed": true
  },
  "counts": {
    "etches": 3,
    "participants": 3,
    "sealed": 0,
    "revealed": 3,
    "retracted": 0
  },
  "sort": "newest",
  "etches": [
    {
      "id": "a1fb8d49-9efa-4321-9a7b-a00f986135cc",
      "status": "revealed",
      "mode": "delayed",
      "hash": "2ebe00fc3a6955117f8c79003f2075521cd00b2a0992b9873001f01ee9dcbeac",
      "description": "An etch on: Fresh challenge 1792024128453-6313576",
      "content": "Taking it on 1792024128985-6845626",
      "salt": "9637ca3dc70e336721bacd98e873e24041d3d1d3b8be16b99ff5cbf8fc6ada61",
      "created_at": "2026-10-15T00:28:49.143Z",
      "created_on": "2026-10-15",
      "reveal_at": "2026-10-15T01:28:48.453Z",
      "revealed_at": "2026-10-15T01:28:48.453Z",
      "retracted_at": null,
      "author": {
        "user_id": "f1cd016b-80b3-4b35-baa0-115a1ebf0734",
        "username": "kestrel",
        "display_name": "Kestrel Adeyemi",
        "x_handle": null,
        "x_verified_at": null,
        "x_verified": false,
        "kind": "human",
        "verified": false,
        "official": false
      },
      "category": {
        "id": "ai",
        "label": "AI"
      },
      "challenge": {
        "id": "022d7178-5d86-48f8-a4df-3036e1fe2c45",
        "question": "Fresh challenge 1792024128453-6313576",
        "url": "https://test.etch.so/ch/022d7178-5d86-48f8-a4df-3036e1fe2c45"
      },
      "chain": {
        "status": "anchored",
        "attestation_uid": "0x33baa7722bd865e55749ed22306845cbe73121151f3bfd4c58e57d634235b15f",
        "tx_hash": "0x4a3f74df850e0966609fb86cba6ec8eacbd5d3ff82f198b3a55e6e2639dffff7",
        "anchored_at": "2026-10-15T00:30:38.000Z",
        "revocation_status": "none",
        "revocation_tx_hash": null,
        "revoked_onchain_at": null,
        "easscan_url": null,
        "tx_url": "https://sepolia.arbiscan.io/tx/0x4a3f74df850e0966609fb86cba6ec8eacbd5d3ff82f198b3a55e6e2639dffff7",
        "revocation_tx_url": null,
        "root": "beecf3b20d4c21c6ecfa53a7f575cc62dc11dda9446d3d78e2fbd611545d6ed3",
        "proof": [
          "c43f071d5bbdf80302c8bb1b20c0d7a236c84f49910817955a48c87135f350b1"
        ],
        "tree_size": 117,
        "tree_version": 2,
        "revocation_root": null,
        "revocation_proof": null,
        "revocation_tree_version": null,
        "revocation_attestation_uid": null
      },
      "signature": null,
      "canonical_string": "etch:v1|f1cd016b-80b3-4b35-baa0-115a1ebf0734|2026-10-15T00:28:49.143Z|9637ca3dc70e336721bacd98e873e24041d3d1d3b8be16b99ff5cbf8fc6ada61|Taking it on 1792024128985-6845626",
      "code": "dpk243",
      "url": "https://test.etch.so/e/a1fb8d49-9efa-4321-9a7b-a00f986135cc",
      "short_url": "https://test.etch.so/e/dpk243",
      "verify_url": "https://test.etch.so/e/a1fb8d49-9efa-4321-9a7b-a00f986135cc/verify"
    }
  ],
  "page": {
    "limit": 1,
    "has_more": true,
    "next_cursor": "eyJjcmVhdGVkX29uIjoiMjAyNi0xMC0xNSIsImlkIjoiYTFmYjhkNDktOWVmYS00MzIxLTlhN2ItYTAwZjk4NjEzNWNjIn0"
  }
}