Vaarta/API Guides

Vaarta API Guides

Practical notes for integrating the Competitive Signals API. For the full endpoint reference, see the API Reference.

Authentication

Create a key in the dashboard under Settings → API Keys. The raw key is shown once — copy it immediately; only its hash is stored. Send it as a Bearer token on every request:

Authorization: Bearer vt_live_xxxxxxxx…

A 401 means the key is missing, malformed, or revoked — the response never distinguishes which, to prevent key enumeration. Rotation: a workspace may hold up to 5 active keys. To rotate, generate a new key, deploy it, then revoke the old one. Revocation is immediate and permanent (soft-delete); revoked keys keep returning 401.

Rate limits

Plan tierRequests / minute/v1/snapshot per hour
Free60— (starter+ only)
Starter603
Pro603
Team603

The per-minute limit is enforced per key (default 60 RPM across all tiers). Exceeding it returns 429 with a Retry-After header (seconds until the window frees up). /v1/snapshot has a separate hard cap of 3 accepted calls per rolling hour because each triggers a real collection run. The limiter fails closed: if the rate-limit check itself errors, the request is rejected with 429 rather than passed through.

Webhook signature verification

Every webhook POST carries three headers:

  • X-Vaarta-Signaturesha256= followed by the HMAC-SHA256 of the raw request body, hex-encoded.
  • X-Vaarta-Timestamp — Unix seconds when the delivery was signed.
  • X-Vaarta-Delivery — a per-delivery UUID, useful for idempotency.

Verify each delivery against your subscription secret (shown once on creation). The body is canonical JSON (object keys sorted) — HMAC the exact raw bytes you receive, do not re-serialize:

expected = "sha256=" + hex( HMAC_SHA256(secret, raw_request_body) )

# 1. constant-time compare against the header
if not constant_time_equals(expected, header["X-Vaarta-Signature"]):
    reject  # 401 — bad signature

# 2. reject stale deliveries (replay protection)
if abs(now_unix_seconds - header["X-Vaarta-Timestamp"]) > 300:
    reject  # signature is valid but the delivery is too old

The timestamp exists to defeat replay attacks: an attacker who captures a valid signed payload cannot resubmit it later, because your receiver rejects deliveries outside a short freshness window (e.g. 5 minutes).

← Back to the API Reference