TraktorAPI
Get API key

Notifications

The list an account's alert matches land in, how to mark it read, and the webhooks they are posted to.

No socket carries notifications: a program reads them from these routes or has them posted to a webhook of its own, and Traktor's Telegram bot sends them to a chat linked on Alerts.

GET /v1/notifications

https://api.traktor.fun

The notifications the account's alerts wrote, newest first, a page at a time.

Credential
API key, browser session or Traktor sign-in
  • limitintegerquery

    Notifications per page.

    Default 301–100

  • cursorcursorquery

    meta.page.cursor from the previous page.

  • unreadbooleanquery

    true for unread only, false for read only; absent for both.

  • alertuuidquery

    One of the account's alerts: its notifications alone, paged by their own cursor, without the suppression summaries its matches were counted into, which belong to no alert; absent for every alert's.

Limits

  • Requests120 a minute, per account
  • Session checks120 a minute, per IP
  • Invalid keys30 a minute, per IP
  • Detailed notifications300 a clock hour, per account
  • Kept for90 days, per account

Errors

invalid_limit, invalid_cursor, invalid_unread_filter, invalid_alert, unknown_query_parameter, duplicate_query_parameter, missing_credentials, invalid_key, key_revoked, subscription_inactive, session_expired, sign_in_required, method_not_allowed, rate_limited, rate_limit_unavailable, internal_error

curl -s "https://api.traktor.fun/v1/notifications?limit=20&alert=8f14e45f-ceea-467a-9575-2b0f3e8d1c2a" \
  -H "Authorization: Bearer $TRAKTOR_API_KEY"
Response 200
{
  "data": {
    "notifications": [
      {
        "id": "0b7c2d4e-1f3a-4b5c-8d6e-7f8091a2b3c4",
        "alertId": "8f14e45f-ceea-467a-9575-2b0f3e8d1c2a",
        "alertName": "Large BNB buys",
        "sourceKey": "flow:bnb:0x4b8e2f6a1c7d9035e8b2a4f6c1d3e5a7b9c0d2e4f6a8b1c3d5e7f9a0b2c4d6e8:0",
        "title": "Large BNB buys triggered",
        "body": "Trade size matched at $1.2k.",
        "reason": {
          "kind": "alert_trigger",
          "mode": "crossing",
          "ruleHash": "227e1305a2a8d5728b6bdd47502abfaa",
          "subjectKey": "bnb:0x2222222222222222222222222222222222222222:0x1111111111111111111111111111111111111111",
          "conditions": [
            {
              "metric": "usdAmount",
              "op": "gte",
              "value": 1000,
              "observed": 1204.5
            }
          ]
        },
        "context": {
          "chain": "bnb",
          "platform": "fomo",
          "tokenAddress": "0x2222222222222222222222222222222222222222",
          "ticker": "EXAMPLE",
          "name": "Example"
        },
        "arrivedAt": "2026-10-03T12:00:02.120Z",
        "occurredAt": "2026-10-03T12:00:00.000Z",
        "createdAt": "2026-10-03T12:00:02.300Z",
        "readAt": null
      }
    ]
  },
  "meta": {
    "requestId": "req_01m40t5ek8b3x7r2mh5q",
    "generatedAt": "2026-10-03T12:00:04.210Z",
    "asOf": null,
    "caveats": [],
    "page": {
      "cursor": null,
      "hasMore": false,
      "limit": 20,
      "returned": 1
    }
  }
}

The list is ordered on (createdAt, id): send meta.page.cursor back as cursor for the next page, and it is null on the last. A query parameter the route does not read is 400 unknown_query_parameter, and one given twice 400 duplicate_query_parameter.

Each notification carries three clocks: occurredAt, when what matched happened in the market, such as a trade's block time; arrivedAt, when Traktor stored it, which cooldowns count from; and createdAt, when the notification was written. readAt is null until it is marked read. A rule's notification has reason.kind alert_trigger, and reason.conditions holds each condition with the figure it observed.

Delivery limits

Past the Detailed notifications limit on the list's block, a match still advances its rule's trigger state, but it is counted into one suppression summary for the hour instead of written on its own. The summary turns unread again each time it grows but keeps its place in the list, so marking all read through a newer notification marks it read again. Evaluation per account each minute is bounded too, and so are the subjects a rule keeps trigger state for; GET /v1/alert-capabilities publishes both bounds under limits. What either bound skipped is never treated as no match: it is counted in a summary of its own, which turns unread and moves to the top of the list each time it grows.

A summary has alertId: null, and its reason.kind is notification_suppression or alert_resource_limit. It belongs to no rule, so a rule's own list (alert=<id>) leaves out the matches counted into one. Notifications, read or not, are deleted after the days on the list's block, and so is a rule's trigger state for a subject it has not updated in that time.

Read and unread

GET /v1/notifications/unread-count

https://api.traktor.fun

How many of the account's notifications are unread.

Credential
API key, browser session or Traktor sign-in

Limits

  • Requests120 a minute, per account
  • Session checks120 a minute, per IP
  • Invalid keys30 a minute, per IP

Errors

missing_credentials, invalid_key, key_revoked, subscription_inactive, session_expired, sign_in_required, method_not_allowed, rate_limited, rate_limit_unavailable, internal_error

curl -s "https://api.traktor.fun/v1/notifications/unread-count" \
  -H "Authorization: Bearer $TRAKTOR_API_KEY"
Response 200
{
  "data": {
    "unreadCount": 3
  },
  "meta": {
    "requestId": "req_01m40t5ek8b3x7r2mh5q",
    "generatedAt": "2026-10-03T12:00:04.210Z",
    "asOf": null,
    "caveats": []
  }
}

POST /v1/notifications/read

https://api.traktor.fun

Marks notifications read: named ones, or all of them up to an optional bound.

Credential
API key, browser session or Traktor sign-in
  • idslistbody

    Notification ids, 1 to 100 of them.

    up to 100 items

  • allbooleanbody

    Every unread notification.

  • throughobjectbody

    With all: the newest notification to mark, as its createdAt and id.

Limits

  • Requests120 a minute, per account
  • Session checks120 a minute, per IP
  • Invalid keys30 a minute, per IP

Errors

invalid_notification_ids, invalid_notification_bound, invalid_json, invalid_body, unknown_field, body_too_large, missing_credentials, invalid_key, key_revoked, subscription_inactive, session_expired, sign_in_required, method_not_allowed, rate_limited, rate_limit_unavailable, internal_error

curl -s -X POST "https://api.traktor.fun/v1/notifications/read" \
  -H "Authorization: Bearer $TRAKTOR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"all":true}'
Response 200
{
  "data": {
    "updated": 3,
    "unreadCount": 0
  },
  "meta": {
    "requestId": "req_01m40t5ek8b3x7r2mh5q",
    "generatedAt": "2026-10-03T12:00:04.210Z",
    "asOf": null,
    "caveats": []
  }
}

Send the newest notification your reader saw as through, so one that arrived since stays unread; a createdAt with the milliseconds the list gives covers that whole millisecond. A malformed through, or one sent without all, is 400 invalid_notification_bound. An id already read, or not the account's, is passed over: updated counts what changed, beside the unreadCount left.

Webhooks

An account names up to three HTTPS endpoints, and each is posted every notification written after it was made, within seconds, oldest first, in batches of up to 20. A post carries the list's own notifications, so a program can take them pushed or read them here and handle both the same way.

GET /v1/webhooks

https://api.traktor.fun

The account's webhooks, oldest first, each with how its last post went; never their secrets.

Credential
API key, browser session or Traktor sign-in

Limits

  • Requests120 a minute, per account
  • Session checks120 a minute, per IP
  • Invalid keys30 a minute, per IP

Errors

missing_credentials, invalid_key, key_revoked, subscription_inactive, session_expired, sign_in_required, method_not_allowed, rate_limited, rate_limit_unavailable, internal_error

curl -s "https://api.traktor.fun/v1/webhooks" \
  -H "Authorization: Bearer $TRAKTOR_API_KEY"
Response 200
{
  "data": {
    "webhooks": [
      {
        "id": "3c9a7b1e-5d2f-4e8a-9b6c-0f1e2d3c4b5a",
        "url": "https://bot.example.com/traktor",
        "enabled": true,
        "disabledReason": null,
        "failures": 0,
        "lastStatus": 200,
        "lastError": null,
        "lastAttemptAt": "2026-10-03T12:00:04.000Z",
        "lastDeliveredAt": "2026-10-03T12:00:04.000Z",
        "createdAt": "2026-10-01T09:00:00.000Z"
      }
    ]
  },
  "meta": {
    "requestId": "req_01m40t5ek8b3x7r2mh5q",
    "generatedAt": "2026-10-03T12:00:04.210Z",
    "asOf": null,
    "caveats": []
  }
}

POST /v1/webhooks

https://api.traktor.fun

Adds an endpoint that every notification the account's alerts write from now on is posted to, while the key or Mini App session that made it lives, signed with the secret this answer alone carries.

Credential
API key, browser session or Traktor sign-in
  • urlstringrequiredbody

    The endpoint: https://, port 443, a host on the public internet, at most 2,048 characters.

Limits

  • Requests120 a minute, per account
  • Session checks120 a minute, per IP
  • Invalid keys30 a minute, per IP
  • Webhooks3 kept, per account

Errors

invalid_webhook_url, webhook_limit_reached, invalid_json, invalid_body, unknown_field, body_too_large, missing_credentials, invalid_key, key_revoked, subscription_inactive, session_expired, sign_in_required, method_not_allowed, rate_limited, rate_limit_unavailable, internal_error

curl -s -X POST "https://api.traktor.fun/v1/webhooks" \
  -H "Authorization: Bearer $TRAKTOR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://bot.example.com/traktor"}'
Response 201
{
  "data": {
    "webhook": {
      "id": "3c9a7b1e-5d2f-4e8a-9b6c-0f1e2d3c4b5a",
      "url": "https://bot.example.com/traktor",
      "enabled": true,
      "disabledReason": null,
      "failures": 0,
      "lastStatus": null,
      "lastError": null,
      "lastAttemptAt": null,
      "lastDeliveredAt": null,
      "createdAt": "2026-10-01T09:00:00.000Z",
      "secret": "tk_whsec_4fQ9xZ2mR7bK1vT8nW3cY6pL0sH5jD2a"
    }
  },
  "meta": {
    "requestId": "req_01m40t5ek8b3x7r2mh5q",
    "generatedAt": "2026-10-03T12:00:04.210Z",
    "asOf": null,
    "caveats": []
  }
}

url is https on port 443, with no user, password or #fragment, and a host on the public internet: an address in a private, loopback, link-local, documentation or other reserved range, a name with no dot, and a name under .local, .internal, .localhost, .lan, .home, .corp or .arpa are 400 invalid_webhook_url, and a fourth endpoint is 409 webhook_limit_reached. The answer carries secret this once and no route shows it again, so store it then. Delivery starts after the account's newest notification, so a new endpoint is sent no backlog.

An endpoint lives no longer than the credential that made it. One made with an API key, or with a browser session that key opened, stops for good when the key is revoked or expires, and one made from Traktor's Telegram Mini App stops for good when that Telegram leaves the account, even if it is linked again; the list then shows it switched off, with disabledReason key_revoked or telegram_unlinked. One made from your Traktor sign-in lives as long as the account. Your profile's API tab lists every endpoint and deletes one.

DELETE /v1/webhooks/{id}

https://api.traktor.fun

Deletes a webhook; nothing more is posted to it.

Credential
API key, browser session or Traktor sign-in
  • iduuidrequiredpath

    The webhook's id.

Limits

  • Requests120 a minute, per account
  • Session checks120 a minute, per IP
  • Invalid keys30 a minute, per IP

Errors

webhook_not_found, route_not_found, missing_credentials, invalid_key, key_revoked, subscription_inactive, session_expired, sign_in_required, method_not_allowed, rate_limited, rate_limit_unavailable, internal_error

curl -s -X DELETE "https://api.traktor.fun/v1/webhooks/3c9a7b1e-5d2f-4e8a-9b6c-0f1e2d3c4b5a" \
  -H "Authorization: Bearer $TRAKTOR_API_KEY"

Response 204: no body.

POST /v1/webhooks/{id}/test

https://api.traktor.fun

Posts a signed batch with no notifications to the endpoint now, and answers what it said: delivered on a 2xx, its status, and error when none came back.

Credential
API key, browser session or Traktor sign-in
  • iduuidrequiredpath

    The webhook's id.

Limits

  • Requests120 a minute, per account
  • Session checks120 a minute, per IP
  • Invalid keys30 a minute, per IP
  • Webhook tests6 a minute, a burst of 3, per account

Errors

webhook_not_found, route_not_found, missing_credentials, invalid_key, key_revoked, subscription_inactive, session_expired, sign_in_required, method_not_allowed, rate_limited, rate_limit_unavailable, internal_error

curl -s -X POST "https://api.traktor.fun/v1/webhooks/3c9a7b1e-5d2f-4e8a-9b6c-0f1e2d3c4b5a/test" \
  -H "Authorization: Bearer $TRAKTOR_API_KEY"
Response 200
{
  "data": {
    "delivered": true,
    "status": 200,
    "error": null
  },
  "meta": {
    "requestId": "req_01m40t5ek8b3x7r2mh5q",
    "generatedAt": "2026-10-03T12:00:04.210Z",
    "asOf": null,
    "caveats": []
  }
}

A test posts a signed batch with test: true and no notifications, and answers what the endpoint did: delivered, its status, and an error when it failed. It moves nothing, so it works on an endpoint that was switched off too.

A post

Each post is a POST of { "webhookId", "test", "notifications" } as JSON, with the headers traktor-webhook-id and traktor-signature: t=<unix seconds>,v1=<hex>, where v1 is the HMAC-SHA256 of <t>.<body> under the endpoint's secret. Compute it over the body's raw bytes before parsing them, compare it in constant time, and refuse a t far from your own clock so an old post cannot be replayed.

Failures and retries

A 2xx moves the endpoint past what it was sent. Anything else keeps it where it was: another status, a redirect (never followed), no answer within 5 seconds, or a host that resolves to an address off the public internet, which is never posted to. The batch is tried again after 30 seconds, then after twice as long each time, at most an hour apart. After 30 failures in a row, about a day, the endpoint is switched off with disabledReason failing; to restart it, delete it and create it again, which starts from the newest notification, and read what it missed from the list. The list shows each endpoint's failures, lastStatus, lastError, lastAttemptAt and lastDeliveredAt.

Delivery is at least once: a post your endpoint kept but answered too late for is sent again, so key on each notification's id. A notification_suppression summary is posted when it is first written and not again as its count grows; an alert_resource_limit summary moves to the top of the list when it grows, and is posted again each time.

    Notifications · Traktor API