Agent Runtime
Status: Connected
Parsing documentation...
Extracted api references
Generating type definitions...
opensteeropensteer
Y Combinator logoBacked by Y Combinator.

The most comprehensive browser automation framework for AI

Enterprise-grade automation at scale.

Custom plans, unlimited concurrent sessions, dedicated proxies, and advanced support for teams that need more.

+ self-service sso
+ unlimited concurrent sessions
+ custom audit logs
+ advanced captcha bypass
+ dedicated support
view pricing

Simple, transparent pricing.

Start for free, upgrade when you need to scale. Everything you need to build robust AI agents.

Cloud Public APIs

API: Webhooks

Configure scraper run webhooks and verify signatures safely.

Webhook Configuration

POST /scrapers/:slug/runs accepts optional webhook settings:

  • webhook.url
  • webhook.secret
  • webhook.events (run.succeeded, run.failed)

OpenSteer signs outgoing webhook payloads using x-opensteer-signature.

Signature Header Format

  • Header name: x-opensteer-signature
  • Format: t=<unix_seconds>,v1=<hex_hmac>
  • Signed payload: <timestamp>.<raw_request_body>

Queue Run Example

curl -X POST "https://api.opensteer.com/scrapers/my-scraper/runs" \
  -H "x-api-key: osk_xxx" \
  -H "Idempotency-Key: req_12345" \
  -H "content-type: application/json" \
  -d '{
    "input": {},
    "webhook": {
      "url": "https://example.com/webhooks/scraper",
      "secret": "whsec_xxx",
      "events": ["run.succeeded", "run.failed"]
    }
  }'

Signature Verification Example (Node.js)

import { createHmac, timingSafeEqual } from "node:crypto"

export function verifyWebhookSignature({
  body,
  header,
  secret,
}: {
  body: string
  header: string
  secret: string
}): boolean {
  const parts = Object.fromEntries(
    header.split(",").map((part) => {
      const [k, ...rest] = part.split("=")
      return [k.trim(), rest.join("=").trim()]
    })
  )

  const timestamp = parts.t
  const signature = parts.v1
  if (!timestamp || !signature) return false

  const payload = `${timestamp}.${body}`
  const expected = createHmac("sha256", secret).update(payload).digest("hex")
  const actualBytes = Buffer.from(signature, "utf8")
  const expectedBytes = Buffer.from(expected, "utf8")
  if (actualBytes.length !== expectedBytes.length) return false
  return timingSafeEqual(actualBytes, expectedBytes)
}

Covered Features

  • api:POST /scrapers/:slug/runs