API help

Everything you need to pull a sniche feed into production: authentication, endpoints, pagination, output formats, limits and error handling.

Quickstart

Three calls and you have data. Everything below assumes your key is in the SNICHE_API_KEY environment variable.

bash
# 1 — check the key works and see your entitlements
curl -s https://api.sniche.com/v1/feeds \
  -H "Authorization: Bearer $SNICHE_API_KEY"

# 2 — pull the first page of a feed
curl -s "https://api.sniche.com/v1/feeds/mal-domains?limit=100" \
  -H "Authorization: Bearer $SNICHE_API_KEY"

# 3 — poll again later using the cursor from step 2
curl -s "https://api.sniche.com/v1/feeds/mal-domains?since=cur_9ad3f01e" \
  -H "Authorization: Bearer $SNICHE_API_KEY"

Authentication

Every request carries your key as a bearer token. Keys are issued per environment (sandbox and production) and can be scoped to specific feeds and source IP ranges from the account dashboard.

Header
Authorization: Bearer sk_live_7f3c9a21b40d8e6512ff90ab
Keep keys server-side. A key in browser or mobile code is a public key. If one leaks, rotate it from the dashboard — the old key keeps working for a one-hour overlap so you can deploy without downtime.

Base URL & versioning

BASE https://api.sniche.com/v1

The version is pinned in the path. We add fields without notice, so parse defensively and ignore unknown keys — but we never remove or repurpose a field inside a version. Breaking changes ship as /v2, and the previous version is supported for at least twelve months after that.

Sandbox keys hit the same host and return the same schema against capped sample data, so you can build the whole integration before your production key is issued.

List feeds

GET /v1/feeds

Returns every feed your key can read, with its cadence, formats and your current entitlement. Free — this call is not metered.

200 OK
{
  "data": [
    {
      "slug": "mal-domains",
      "name": "Malicious Domains",
      "cadence_seconds": 300,
      "formats": ["json", "csv", "stix"],
      "entitled": true,
      "records_total": 4128377
    }
  ]
}

Fetch records

GET /v1/feeds/{slug}

The main endpoint. Without since it returns the newest records; with it, everything added or changed after that cursor.

ParameterTypeDefaultDescription
sincestring Cursor from a previous response, or an ISO-8601 timestamp. Returns records after that point.
limitinteger100 Records per page, 1–1000. Bulk snapshots ignore this.
formatstringjson One of json, ndjson, csv, stix.
min_confidenceinteger0 Drop records scored below this value (0–100). Most teams block at 80+.
fieldsstring Comma-separated allow-list of fields, to cut response size.
include_retractedbooleanfalse Include withdrawn indicators so you can un-block them.
Request
curl -s -G https://api.sniche.com/v1/feeds/c2-track \
  -H "Authorization: Bearer $SNICHE_API_KEY" \
  --data-urlencode "since=2026-08-19T00:00:00Z" \
  --data-urlencode "min_confidence=80" \
  --data-urlencode "limit=250"
200 OK
{
  "feed": "c2-track",
  "cursor": "cur_b71e5c04",
  "has_more": true,
  "count": 250,
  "data": [
    {
      "id": "ind_01J9XQ4M7TZ",
      "type": "ipv4",
      "value": "185.220.***.**",
      "port": 8443,
      "malware_family": "AsyncRAT",
      "confidence": 94,
      "jarm": "2ad2ad0002ad2ad22c42d43d00041d",
      "asn": 200651,
      "country": "NL",
      "first_seen": "2026-08-18T21:44:02Z",
      "last_seen": "2026-08-19T07:12:55Z",
      "source": "sensor",
      "retracted": false
    }
  ]
}

Look up a single indicator

GET /v1/lookup?value={indicator}

Ask about one domain, URL, IP or hash across every feed you are entitled to — useful for enrichment inside a SIEM or a case-management tool. Counts as one record.

200 OK
{
  "value": "secure-login-m365.top",
  "known": true,
  "max_confidence": 92,
  "matches": [
    { "feed": "phish-urls",  "confidence": 92, "brand": "Microsoft 365" },
    { "feed": "nrd",         "registered": "2026-08-17" }
  ]
}

Stream records

GET /v1/feeds/{slug}/stream

Available on Pro and Enterprise. Holds the connection open and writes one JSON object per line as records are confirmed. Reconnect with the last cursor you processed and nothing is lost.

bash
curl -N https://api.sniche.com/v1/feeds/phish-urls/stream \
  -H "Authorization: Bearer $SNICHE_API_KEY" \
  -H "Last-Event-Cursor: cur_b71e5c04"

# {"id":"ind_01J9XQ...","value":"https://verify-account.cc/login","confidence":88}
# {"id":"ind_01J9XR...","value":"https://dhl-track-eu.top/parcel","confidence":91}
Webhooks are an alternative for lower-volume feeds: we POST batches to your endpoint and retry with exponential back-off for 24 hours. Configure them under Account → Delivery.

Usage

GET /v1/usage

Your consumption for the current billing period, broken down by feed. Not metered.

200 OK
{
  "period_start": "2026-08-01",
  "records_included": 10000000,
  "records_used": 6840219,
  "by_feed": {
    "phish-urls": 3120004,
    "mal-domains": 2410880,
    "ip-rep": 1309335
  }
}

Report a false positive

POST /v1/feedback

Send back anything you believe is wrong. Reports are triaged within four hours; confirmed retractions appear in your next poll with "retracted": true.

Request body
{
  "indicator_id": "ind_01J9XQ4M7TZ",
  "verdict": "false_positive",
  "evidence": "Corporate mail gateway, in use since 2021."
}

Pagination & cursors

Cursors are opaque strings that mark a position in the feed's change log. Store the cursor from each response and send it as since next time — you will never receive the same record twice, and never miss one that arrived between polls.

  • Keep paging while has_more is true.
  • Cursors stay valid for 30 days. After that, start from a timestamp.
  • A poll that returns nothing is normal, free, and still advances your cursor.
  • For a cold start, pull the bulk snapshot first, then poll from the cursor it returns.
Recommended polling interval: match the feed's cadence. Polling a five-minute feed every ten seconds returns empty pages and wastes your rate limit.

Record schema

These fields appear on every record, whatever the feed. Feed-specific fields — such as malware_family or brand — are documented on each feed's page in the dashboard.

FieldTypeNotes
idstringStable identifier. Use it as your primary key.
typestringdomain, url, ipv4, ipv6, sha256, cert.
valuestringThe indicator itself, normalised and lower-cased.
confidenceinteger0–100. Block at 80+, alert below it, is a common split.
sourcestringsensor, honeypot, crawler, partner, analyst.
first_seenstringISO-8601 UTC, when we first observed it.
last_seenstringISO-8601 UTC, most recent observation.
retractedbooleanTrue once withdrawn — remove it from your block list.
tagsarrayFree-form labels, e.g. ["credential-theft","kit:evilginx"].

Output formats

JSON

Default. One envelope, records under data. Best for paged polling.

NDJSON

One record per line, no envelope. Best for streaming and for piping straight into a log processor.

CSV

Flat columns, header row included. Feed-specific fields are appended after the common ones.

STIX 2.1

Bundle of indicator objects with patterns, for platforms that speak structured threat exchange.

Rate limits

Limits are per key, measured in a sliding window. Every response tells you where you stand.

Response headers
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 284
X-RateLimit-Reset: 1755590400
Retry-After: 12          # only on 429
PlanRequests / minuteConcurrent streamsBulk snapshots / day
Core602
Pro300412
EnterpriseNegotiatedNegotiatedUnlimited

On 429, wait for Retry-After seconds. Retrying immediately extends the window.

Errors

Errors use standard status codes with a machine-readable body. The request_id is what support needs to trace a call.

403 Forbidden
{
  "error": {
    "code": "feed_not_entitled",
    "message": "Your plan does not include the feed 'pdns'.",
    "request_id": "req_01J9XQ8M2KD",
    "docs": "https://sniche.com/api.html#errors"
  }
}
StatusCodeWhat to do
400invalid_parameterCheck the message — it names the offending parameter.
401invalid_keyKey missing, malformed or revoked. Re-read the Authorization header.
403feed_not_entitledYour plan does not include this feed. Contact sales to add it.
403ip_not_allowedThe key is IP-scoped and this source is not on the list.
404unknown_feedCheck the slug against GET /v1/feeds.
409cursor_expiredCursor older than 30 days. Restart from a timestamp.
429rate_limitedBack off for Retry-After seconds.
500internal_errorRetry with jitter. If it persists, send us the request_id.
503maintenancePlanned window. Check the status board.

Acceptable use

The short version of the licence that comes with every key:

  • Use the data inside your own security controls, products and investigations.
  • Do not redistribute or resell raw feed data on Core or Pro plans. Enterprise agreements can include redistribution rights for a defined product.
  • Do not use the data to attack, probe or harass the hosts it describes.
  • Share your key with nobody outside your organisation. Keys are per-customer.
  • Attribute sniche where you display our data to end users, unless your agreement says otherwise.

Questions about licensing? Ask us — we would rather answer up front than argue later.

Ready to build

Get a sandbox key and start integrating

Full schema, capped sample data, no payment details. Usually issued within one business day.