Signalcache API

Score a transaction for fraud in a single request — features fetched, computed, and scored in-memory, server-side p99 under 10ms.

Quickstart

Send a transaction, get back a decision. Here it is in three flavors.

cURL

curl -X POST https://api.signalcache.cloud/v1/score \
  -H "x-api-key: $SIGNALCACHE_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "entity": { "card": "card_9f2a", "device": "dev_abc", "ip": "203.0.113.7", "bin": "411111" },
    "amount": 248.00
  }'

Python

from signalcache import Client

sc = Client("sk_live_...")
d = sc.score(card="card_9f2a", device="dev_abc",
             ip="203.0.113.7", bin="411111", amount=248.00)

if d.is_declined:
    block(d.reason_codes)

Node (fetch)

const r = await fetch("https://api.signalcache.cloud/v1/score", {
  method: "POST",
  headers: { "x-api-key": key, "content-type": "application/json" },
  body: JSON.stringify({ entity: { card, device, ip, bin }, amount }),
});
const d = await r.json();  // { action, score, reason_codes, ... }

Authentication

Every request (except /health) needs your API key, sent either way:

  • x-api-key: <key>
  • Authorization: Bearer <key>

A missing or unknown key returns 401. Keys are scoped to your tenant — your feature state is fully isolated from every other tenant.

Keep keys server-side. Don't ship them in a browser or mobile app; call Signalcache from your backend.

Base URL

Managed cloud:

https://api.signalcache.cloud

Self-hosting in your VPC (Enterprise)? Point any client at your own host — the API is identical.

POST/v1/score

Read the entity's point-in-time features, score them, and record the event for future velocity — all in one call.

Request body

fieldtypenotes
entity.cardstringrequired — your card/account token (not a PAN)
entity.devicestringoptional device id
entity.ipstringoptional IP address
entity.binstringoptional card BIN (first 6)
amountnumbertransaction amount
declinedbooloptional — mark this event as a decline (feeds decline velocity)

Response 200

{
  "event_id": "evt_00000000002a",
  "action": "decline",           // accept | review | decline
  "score": 0.94,                 // 0.0 – 1.0
  "reason_codes": ["velocity_spike", "new_device"],
  "features": { ... },           // the point-in-time features used
  "latency_ms": 0.08,            // server-side scoring time
  "tenant": "acme"
}

Thresholds: score ≥ 0.80decline, ≥ 0.55review, else accept.

POST/v1/ingest

Same body as /v1/score, but only updates the feature store — no scoring, no decision returned. Use it to backfill history or record events you don't need scored. Returns { "ok": true }.

GET/v1/features

Read the current feature vector for an entity without scoring.

GET /v1/features?card=card_9f2a&ip=203.0.113.7&bin=411111

Returns the same features object described in the glossary.

GET/v1/stats

Operational stats for your tenant: entities tracked, decisions served, and server-side latency percentiles.

{ "cards_tracked": 12840, "decisions": 91233,
  "latency_ms": { "p50": 0.02, "p95": 0.07, "p99": 0.22 } }

GET/health

Unauthenticated liveness check. Returns { "ok": true }.

Feature glossary

The features Signalcache computes on the hot path and returns in every decision:

featurewhat it measures
card_txn_velocity_60stransactions from this card in the last 60 seconds
card_txn_velocity_5mtransactions in the last 5 minutes
card_txn_velocity_1htransactions in the last hour
card_amount_sum_5mtotal amount charged to this card in 5 minutes
card_amount_zscorehow anomalous this amount is vs the card's history
card_distinct_devices_24hdistinct devices seen for this card in 24h
card_declines_5mdeclines for this card in the last 5 minutes
ip_distinct_cards_24hdistinct cards seen from this IP in 24h (fan-out)
bin_velocity_estrecent global velocity for this BIN — catches distributed BIN attacks

Reason codes

Human-readable explanations attached to a decision (auditable, dispute-ready):

codemeaning
velocity_spikeunusually high transaction rate for this card
new_devicemore distinct devices than expected
amount_anomalyamount far outside the card's normal range
prior_declinesrecent declines on this card
ip_card_fanoutmany cards from one IP
bin_attack_patternBIN-testing pattern across many cards

Errors & limits

statusmeaning
400malformed request (e.g. missing entity.card)
401missing or invalid API key
429rate limit exceeded — back off and retry
5xxserver error — safe to retry with backoff

Errors return { "error": "..." }. Rate limits depend on your plan; contact us if you need a higher ceiling for load testing.

SDKs

Python

pip install signalcache

See the Python SDK README for the full reference. Other languages: call the JSON API directly (examples above) — more SDKs coming.

Don't have a key yet? Request early access and we'll get you set up.