Build with Nightsec

From first lookup to live data.

Integrate observed proxy intelligence with a small HTTP API. Use the same fields for online lookups, local MaxMind databases, and incremental updates.

Coverage depends on configured proxy probes. Synthetic records are labeled. An unknown IP does not mean it is safe or is not a proxy.

1. Make your first request

Create a free account, then create a key in the console. Set it in your environment:

export NIGHTSEC_API_KEY='your-key-from-the-console'
curl 'https://nightsec.io/v1/lookup/203.0.113.42' \
  -H "Authorization: Bearer $NIGHTSEC_API_KEY"

On a fresh instance, the response is found: false until a configured proxy probe observes it. Documentation IPs are examples.

2. Authenticate safely

All customer API endpoints require Authorization: Bearer <API_KEY>. Keys are shown once and stored as SHA256 hashes. Create separate keys for each environment and revoke unused keys in the console. API keys cannot access admin operations.

Do not put keys in query strings, public frontend code, or logs. Sign in with a single-use eight-digit email code, valid for ten minutes with five verification attempts. Browser account sessions use HttpOnly cookies. Browser mutations must send an Origin matching the configured base URL.

3. Look up single IPs or batches

GET /v1/lookup/{ip} accepts IPv4 and IPv6. Batch requests accept 1–100 addresses and charge one unit for every submitted address, including unknown results.

curl 'https://nightsec.io/v1/lookup' \
  -H "Authorization: Bearer $NIGHTSEC_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"ips":["203.0.113.42","2001:db8::42"]}'

Use GET /v1/me to inspect your plan and monthly quota.

4. Understand an observation

location contains country, country_name, state, city and approximate latitude/longitude where available. geolocation contains source, database date, staleness, lookup time, licence and status. Missing location is null; pending, unavailable and not_found are distinct from a successful lookup. Geo updates do not refresh proxy first/last-seen times. These are estimates of the exit IP, not the location of the person using the proxy. IP2Location LITE geo fields are provided under CC BY-SA 4.0; retain attribution and applicable share-alike terms when reusing the geo data.

FieldMeaning
ipCanonical IPv4 or IPv6 address; exact-address observations.
providerOperator-assigned provider attribution from the source.
classificationproxy, vpn, tor, hosting, or residential.
confidence0–100 assigned evidence score, not a calibrated probability.
countryTwo-letter exit-IP country code from geo enrichment, falling back to historical source attribution; empty if unknown.
first_seen / last_seenUnix seconds UTC. First sighting and most recent observation.
activeWhether the current record is active. Worker retires stale data after 30 days by default.
syntheticTrue for demo/test data. Exclude from real decisions.
source_idConfigured proxy-probe source ID; historical imported records may be null.

Each sighting is stored as a durable event. The current record reflects the most recent source attribution; use event history to inspect previous sightings. Classification is evidence for a decision, not an automatic fraud verdict.

Security intelligence · prepared category

Current collection covers configured proxy networks, not VPN services. No DDoS-for-hire or public stresser feed is connected yet. This category records exact-IP service associations independently of proxy sightings. An advertisement is not an observed attack, and an association does not prove an IP attacked your service.

GET /v1/security/{ip} uses your API key and one lookup unit. It returns current associations, each with category, service name, evidence type, source URL, report reference and observation/expiry times. A current, non-synthetic proxy observation on the same IP is included separately in proxy_observation. This exact-IP overlap is context, not proof of common ownership or malicious intent. Empty results mean no current evidence.

Security evidence is currently available through this separate lookup endpoint; proxy MMDB releases and the proxy change stream do not include it. No calibrated risk score is assigned.

5. Bootstrap a local MaxMind database

Pro and Business plans include immutable .mmdb and JSONL snapshots. Fetch the manifest, download the file using its relative URL, verify SHA256, then atomically replace your local database.

curl 'https://nightsec.io/v1/releases/latest' \
  -H "Authorization: Bearer $NIGHTSEC_API_KEY"
# Download files["iplens.mmdb"].url with the same bearer header.
# Verify files["iplens.mmdb"].sha256 before replacing the live file.

pip install maxminddb
python - <<'PY'
import maxminddb
with maxminddb.open_database('iplens.mmdb') as database:
    print(database.get('203.0.113.42'))
PY

For existing integrations, Nightsec retains the download filename iplens.mmdb and schema identifier. The database uses the MaxMind file format with the custom IPLens-Proxy schema. Use a generic MMDB reader, rather than GeoIP2 city-specific models. It is not a MaxMind GeoIP data product. A miss returns null. Snapshot files remain immutable; changes require downloading another release or maintaining an overlay.

The manifest includes cursor, count, created_at, file sizes, and checksums. Start the change stream after that cursor. We capture records and the cursor in one serialized transaction, so changes committed later can be replayed.

6. Follow the HTTP change stream

Use SSE with bearer authentication. The server emits upsert and delete events. Each event has a monotonic ID and a complete observation payload.

curl -N 'https://nightsec.io/v1/stream?after=SNAPSHOT_CURSOR' \
  -H "Authorization: Bearer $NIGHTSEC_API_KEY" \
  -H 'Accept: text/event-stream'

id: 42
event: upsert
data: {"id":42,"operation":"upsert","data":{"ip":"203.0.113.42",...}}

# Reconnect after the last event successfully applied:
curl -N 'https://nightsec.io/v1/stream' \
  -H "Authorization: Bearer $NIGHTSEC_API_KEY" \
  -H 'Last-Event-ID: 42'

Persist a cursor only after applying its event. Delivery is at least once; deduplicate by ID. Apply delete as a tombstone that hides a snapshot record; apply upsert to your overlay. MMDB files cannot be edited in place. Connections rotate after 55 seconds and emit a reconnect event. Reconnect with backoff and your saved cursor. Heartbeat comments arrive while idle. The stream closes when access or the key is revoked.

For finite polling, use GET /v1/events?after=42&limit=100. Apply events in order, save next_cursor, and fetch another page while has_more is true. /v1/stream?once=true returns one page (up to 100 events) for diagnostics. Prototype event history is retained indefinitely; operate storage retention explicitly before production.

7. Handle limits and errors

Developer: 1,000 lookups/month. Pro: 100,000. Business: 1,000,000. Quotas reset by UTC calendar month. All plans allow 600 authenticated API requests per minute per account. SSE allows 30 connection starts per minute per account. Stream events and downloads do not consume lookup quota.

StatusAction
401Supply a valid, non-revoked API key.
403Upgrade for delivery or use the required account role.
404The requested release has not been published.
409The resource is busy or conflicts with an existing subscription.
422Fix request validation; inspect the JSON detail field.
429Respect Retry-After for rate limits; monthly exhaustion requires reset or an upgrade.
502 / 503Temporary dependency failure or missing configuration. Retry with backoff.

Invalid request bodies are not charged. Unknown but valid IPs consume quota. Batch charging is atomic: the whole batch is accepted or rejected.

8. Subscription access

Stripe Checkout collects payments. Only confirmed active or trialing subscriptions receive paid access. Returning from Checkout does not grant access. Subscription changes, renewal, payment failures, and cancellation are reconciled from Stripe webhooks. Past-due, unpaid, paused, incomplete, and canceled subscriptions fall back to Developer access. A cancellation scheduled for period end retains access while Stripe still reports active.

Use the console’s billing portal to change payment methods, view invoices, or cancel. The local demo entitlement is explicitly marked and does not represent a payment.