SurfacedBySurfacedBy Docs

Triggering a Scan

End-to-end walkthrough of submitting a Console scan and consuming the result.

Ask an AI:Open in ChatGPTOpen in Claude

This guide walks through a scan from credit purchase to result retrieval.

Prerequisites

  • A Console account at console.surfacedby.com.
  • At least one credit pack purchased (the minimum, 100 Credits for $10, covers 5 base scans).
  • An API key minted from the Console dashboard under Keys. Both live (sk_live_) and test (sk_test_) prefixes are supported; test keys run against the sandbox and never consume credits.

Step 1: Preview the cost

Before committing, preview the credit cost for the exact payload you plan to submit:

curl -X POST https://api.surfacedby.com/api/v1/console/scans/preview \
  -H "X-API-Key: sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "yourbrand.com",
    "keywords": ["ai visibility", "generative engine optimization", "llm seo"],
    "platforms": ["chatgpt", "claude", "perplexity", "gemini"],
    "add_ons": ["strategic_brief"]
  }'

The response includes the total credits required and a breakdown by component. No credits are consumed by preview.

Step 2: Submit the scan

Use the same payload against POST /api/v1/console/scans:

curl -X POST https://api.surfacedby.com/api/v1/console/scans \
  -H "X-API-Key: sk_live_..." \
  -H "Idempotency-Key: 9f8e2b1a-0c4d-4a7e-8b3f-5d1e2a3c6d7f" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "yourbrand.com",
    "keywords": ["ai visibility", "generative engine optimization", "llm seo"],
    "platforms": ["chatgpt", "claude", "perplexity", "gemini"],
    "add_ons": ["strategic_brief"]
  }'

The response is immediate and includes:

  • scan_id: the identifier you use to fetch results.
  • status: queued or running.
  • credits_consumed: how many credits were deducted from your balance for this scan.
  • balance_after: your remaining credit balance after the deduction.

If your balance is insufficient, the request returns 402 Payment Required with required_credits, current_balance, and a purchase_url you can redirect the user to.

The Idempotency-Key header is optional but recommended. Retrying with the same key returns the original response rather than submitting a duplicate scan.

Step 3: Wait for completion

You have two options to know when the scan is done.

Register a webhook endpoint through the Console dashboard or the API. When the scan finishes, we POST a signed JSON payload to your URL with event = scan.completed (or scan.failed on terminal failure). See Webhooks for signature verification and the full event schema.

Option B: Polling

If a webhook is not a fit, poll GET /api/v1/console/scans/{scan_id}:

curl https://api.surfacedby.com/api/v1/console/scans/SCAN_ID_HERE \
  -H "X-API-Key: sk_live_..."

A scan progresses through queued, running, and either completed or failed. A typical scan takes a few minutes; complex scans with many keywords and add-ons can take longer.

Step 4: Read the results

On completion, the GET /api/v1/console/scans/{scan_id} response includes the full result set: per-platform coverage, citation counts, brand mentions, sentiment scores (if the add-on was selected), competitor list, and any add-on outputs you requested. The schema matches the Data API analytics response for the same scan type.

Handling failures

If the scan terminally fails (not retryable on our side), the credits are automatically refunded to your balance and a scan.failed webhook is delivered. Your ledger shows the refund with reason scan_refund; you can read your ledger via GET /api/v1/console/credits/ledger.

Transient failures during the scan are retried internally and do not affect your balance. You only ever pay for work that reached a terminal state.

Cancelling a scan

POST /api/v1/console/scans/{scan_id}/cancel stops a scan and returns its new state. Whether credits come back depends on how far the scan got:

  • Cancelled while pending (the worker has not started): the full debit is refunded. The response body reports refunded_credits equal to the original charge.
  • Cancelled while running (the worker is already spending provider budget on your keywords): credits stay debited. We do not attribute per-query provider cost back to credits in v1, so a mid-run cancel keeps the original charge.

The response includes prior_status (pending or running) so your client can surface the distinction to the end user.

On this page