Beetle API Docs

Beetle API

Classify a merchant against the right MCC and keep dated evidence of what the merchant sold and which policies it published.

Base URL: https://alpha.api.getbeetle.in · API version 1.0.0

All prices are in INR and exclude GST. Timestamps are epoch milliseconds unless noted. Money is returned in major units (rupees), not paise.

Quickstart

  1. Create an account in the dashboard.
  2. Verify your email, then create an API key under Settings → API tokens.
  3. Send a URL to the classification endpoint.
curl
curl -X POST https://alpha.api.getbeetle.in/ \
  -H "Authorization: Bearer $BEETLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://merchant.example"}'

The raw key is shown once at creation. If you lose it, revoke it and create a new one.

Authentication

Every request uses a bearer credential in the Authorization header:

header
Authorization: Bearer <dashboard_token | api_key>
  • API key (bet_live_…) — classification requests. Keys are scoped to the account and can be revoked at any time.
  • Dashboard token — returned by /auth/signup and /auth/login; used for keys, usage, billing, runs, and webhooks.

Missing or invalid credentials return 401. Unknown or foreign run/webhook ids return 404 rather than leaking existence.

API keys

GET/keys

List keys for the account, newest first.

POST/keys

Create a key. Requires a verified email. Body: { "name": "Production" }. Returns the record plus raw, which is never shown again.

DELETE/keys/{id}

Revoke a key immediately. Past usage is retained for audit.

Classify a merchant

POST/

Runs the classifier once for a single URL. Every run fetches policy pages; policy-page bodies are never returned.

FieldTypeNotes
urlstringRequired. One URL only; comma-separated values are rejected.

A run is billable only when at least one policy page resolves to a real URL. MCC alone does not make a run billable. Policy-less runs are recorded as edge_failure, are not billable, and do not consume quota. The response exposes policy-page URLs and confidence scores, not their content.

200 response (illustrative)
{
  "schema_version": "1.0",
  "user_id": 42,
  "billable": true,
  "payload": {
    "request_id": "24a1dc43-ae9d-4650-8eae-95f61d980419",
    "created_at": 1762592000000,
    "websites": [{
      "url": "merchant.example",
      "final_url": "https://merchant.example/",
      "evidences": { "social": {}, "links": [], "product_pages": [] },
      "assessments": {
        "policy_pages": {
          "terms":   { "url": "https://merchant.example/terms",   "confidence": 0.91 },
          "privacy": { "url": "https://merchant.example/privacy", "confidence": 0.88 },
          "legal":   { "url": null, "confidence": 0 },
          "shipping":{ "url": null, "confidence": 0 },
          "refunds": { "url": null, "confidence": 0 }
        },
        "mcc": [
          { "category": "Computer Programming and IT Services", "code": 7372, "confidence": 0.30 },
          { "category": "Information Retrieval Services",       "code": 7375, "confidence": 0.59 }
        ]
      }
    }]
  }
}

Entry plans have a lifetime allowance of 25 checks. When it is exhausted the API returns 402 until the account upgrades.

Usage

GET/usage

Newest-first usage events. Each event carries the key name and, when a stored run exists, its request_id.

QueryDescription
from, toISO 8601 bounds.
domainCase-insensitive substring.
statussuccess · edge_failure · error
key_idInteger API key id.
limit, offsetDefault 100, max 500; offset for pagination.

Event fields: id, api_key_id, key_name, request_id (nullable), domain, status, latency_ms, billable, created_at.

GET/usage/summary

Aggregates a range with interval=day|month. Returns totals and dense, zero-filled buckets ordered ascending.

GET/usage/export

Streams a CSV of the full filtered range (no row cap), header time,key_name,domain,status,timing_ms,billable. Requires from and to.

Evidence & runs

GET/runs/{request_id}

Latest stored run for a request. Accepts a dashboard token or an API key.

GET/runs/{request_id}/{run_id}

Specific run. run_id is latest, genesis, or a numeric drift run.

GET/runs/{request_id}/versions

Versions ascending by run id: [{ run_id, created_at }]. Use it to build a drift timeline.

Stored runs include websites[].assessments.mcc, websites[].assessments.policy_pages, and websites[].evidences. Newer runs also carry created_at; legacy runs fall back to the version timestamp.

Billing

GET/billing/summary

Current plan, billing period, usage, and next invoice.

FieldMeaning
plan.nameCurrent plan.
plan.pricePer-check rate in major units; null means custom pricing (Enterprise).
plan.currencyISO currency code.
plan.free_checksLifetime allowance, or null when the plan is metered.
period.from, period.toCurrent billing period, epoch ms.
usage.requests, usage.billableRuns and billable runs in the period.
usage.amountPeriod spend in major units, excluding GST.
usage.free_usedLifetime checks consumed against the allowance, account-level and shared by every API key.
next_invoice_atNext invoice date, epoch ms.
GET/invoices?limit=12

Newest-first invoices: id, number, created_at, amount, currency, status (paid | open | void), and optional url.

Webhooks

Manage delivery endpoints for drift notifications. Adding or updating endpoints requires a verified account with remaining checks; entry plans lose add/update access once the lifetime allowance is exhausted, and deliveries stop. Existing endpoints are never deleted by a plan change, and Delete is always allowed.

GET/webhooks
POST/webhooks

Body { "url": "https://..." }. HTTPS only. 400 invalid URL · 403 no access/checks exhausted · 409 duplicate.

PATCH/webhooks/{id}

Update the URL. Changing it resets health to pending and clears the last-check fields.

DELETE/webhooks/{id}

Remove an endpoint. Notifications stop immediately.

POST/webhooks/{id}/test

Sends a synchronous drift.test event and returns { ok, status_code, error }. Gated like add/update.

POST/webhooks/{id}/rotate-secret

Issues a new signing secret and returns it once; the previous secret stops working immediately.

Endpoint object

json
{
  "id": 7,
  "url": "https://example.com/hooks/beetle",
  "status": "healthy",
  "last_checked_at": 1762592000000,
  "last_status_code": 200,
  "last_error": null,
  "created_at": 1762500000000
}

status is healthy, failing, or pending (no delivery attempted yet).

Signing

POST /webhooks returns a one-time secret alongside the endpoint. Deliveries carry X-Beetle-Event, X-Beetle-Timestamp, and X-Beetle-Signature — an HMAC-SHA256 of ${timestamp}.${body} using that secret. Compare in constant time and reject stale timestamps.

Drift events are delivered on a 10s timeout with no redirects; retries run at 1m, 5m, 30m, 2h, and 6h before an endpoint is marked failing. An account may register up to 10 endpoints. Entry-plan deliveries stop when the lifetime check allowance is exhausted.

Errors

Errors return JSON with error and/or message.

StatusMeaning
400Invalid input: URL, range, interval, or path id.
401Missing, invalid, or expired credential.
402Payment required; the lifetime free-check allowance is exhausted.
403Email not verified, or the plan lacks the requested entitlement.
404Unknown id, or an id owned by another account.
409Duplicate resource, such as an already-registered webhook URL.
500Classification or server failure. Safe to retry.

Plans & limits

PlanVolume band (checks/month)Rate per checkEntry allowanceHistory
EvaluationOne-time trialFree25 lifetime90 days
Starter1–1,000₹3025 lifetime12 months
Growth1,001–10,000₹20None12 months
Scale10,001–100,000₹12None36 months
Enterprise100,000+, or by contractCustom, ₹6 floorNoneCustom

Volume bands set the rate for the month's successful checks; they are pricing bands, not hard usage caps. A check is billed only when at least one policy page resolves. Prices exclude GST (18%), and there is no monthly minimum commit.

Changelog

  • 2026-10-28 — Webhook PATCH; webhook entitlement for Evaluation/Starter, credit-gated. Usage filters, export, and per-request evidence.
  • 2026-10-27 — Plan matrix, billing summary and invoices, free-check metadata.
  • 2026-10-26 — Usage summary with daily/monthly buckets.

Questions: support@getbeetle.in