SurfacedBySurfacedBy Docs

Evidence and Improvements

Configure a brand, retrieve answer and citation evidence, and read diagnoses and opportunities from a Console check.

Ask an AI:Open in ChatGPTOpen in Claude

Console can supply measurements and processed insights to your own application without a dashboard subscription. All paths below start with https://api.surfacedby.com/api/v1/console. Send your Console key in X-API-Key.

Discover supported operations

GET /capabilities returns enabled platforms, supported countries and languages, operations, and pricing references. Check these capabilities before offering a connection feature. Models are managed by Console rather than selected by the caller. Offer research or content only when the corresponding operation is advertised as available.

Configure the brand

Before submitting a check, send PATCH /domains/{domain_id}/brand with a brand name, aliases, and optionally a supported two-letter country code:

{
  "brand_name": "Example Studio",
  "aliases": ["ExampleStudio"],
  "country": "US"
}

Send POST /domains/{domain_id}/competitors with {"domain":"competitor.example"} to add or confirm a competitor. The response contains its domain and added or confirmed status. Generic platform domains and the brand's own domain are refused. Both mutations require an Idempotency-Key with API-key authentication.

Approve the check price

Preview a check through POST /scans/preview. When submitting it to POST /scans, include max_credits to enforce the approved price. A price above that integer ceiling returns 409 budget_exceeded before charging. Existing check prices and credit packs apply.

Retrieve observations

GET /scans/{scan_id}/observations returns answer text, the tracked prompt, platform, model, time, country, brand presence, citation position and cited URLs. The surface is api: these are measurements obtained through APIs, not observations of a consumer application's interface.

An unsuccessful answer is missing_observation, with no presence result. It must not be counted as an answer that failed to mention the brand. Retrieved references that were not cited in the answer are excluded from citations.

captured_at records when the original provider answer was received. It stays unchanged when cached is true, meaning the check reused that answer. Historical answers whose capture time is unknown have captured_at: null. Keep this separate from observed_at, which retains the observation's existing timestamp.

Wait for analysis

Check completion means measurement has finished. GET /scans/{scan_id}/analysis separately reports whether processed analysis is pending, available, or unavailable. Wait for available before reading the finished insights for that check. Do not interpret pending analysis as an empty set of findings.

Read diagnoses and opportunities

Fetch GET /domains/{domain_id}/insights/diagnoses?scan_id={scan_id} or GET /domains/{domain_id}/insights/opportunities?scan_id={scan_id}. Findings include an explanation, priority, actionable steps, a target page when known, relevant competitors, and observation references when the producer recorded them. Without scan_id, the current opportunities list only findings that name a concrete change; with scan_id, a check's findings are returned as they were measured.

One change can answer several tracked prompts: questions a single page answers, or questions asked in nearly the same words. Every opportunity finding it covers carries the same change.id; the finding with change.lead true names the change, and change.prompts counts the prompts it answers. Group by change.id to act on each change once. change is null for diagnoses and for findings with no content change.

The optional scan_id limits findings to that check. Without it, findings may span multiple checks; use each finding's scan_id and evidence_period rather than assigning the entire response to the newest check. A missing evidence period is unknown, not proof that the evidence is current. Scores used for internal ranking are not part of these findings.

Recover research and content jobs

When generation is available, request an estimate with POST /domains/{domain_id}/content/estimates/{operation} (research or content). Approve it through POST /content/jobs with the estimate ID, a stable UUID request_key and approved_credits. Retain that request key and approval before sending the request.

GET /content/jobs lists only your account's jobs, newest first. It accepts page_size from 1 to 100, cursor, and optional domain_id, operation, status and request_key filters. Each job includes its public estimate_id, original request_key, progress, approved credits and settlement receipt. A receipt's charged and refunded credits add up to the approved reservation.

If the submission response is lost, use GET /content/jobs?request_key={request_key} to find the original job. Do not create another request key to retry uncertain work. An empty result does not prove that an in-flight submission was rejected; check again later. History and financial job records remain readable when new generation is disabled, including jobs whose website was removed. Evidence results require an active website owned by the same account.

Read status with GET /content/jobs/{job_id}, collect results with GET /content/jobs/{job_id}/results, or request cancellation with POST /content/jobs/{job_id}/cancel. Cancellation may require later confirmation while completed work is reconciled. It does not promise a full refund of work already completed.

Suggest customer questions

Offer suggestions only when GET /capabilities advertises questions. Request POST /domains/{domain_id}/questions/estimate with up to five source_urls on your website, a supported locale, count from 1 to 20 and optional existing_questions to avoid repeats. Console also reads the primary website page to establish its scope independently of the selected pages.

{
  "source_urls": ["https://example.com/products/reporting"],
  "locale": "en-US",
  "count": 12,
  "existing_questions": ["How can I share a report with my team?"]
}

Approve the returned estimate through POST /questions/jobs, using the same estimate_id, stable UUID request_key and approved_credits contract as content. GET /jobs lists all managed operations; use an exact request-key lookup after a lost response. GET /jobs/{job_id} and POST /jobs/{job_id}/cancel share the same status and settlement rules.

Collect GET /questions/jobs/{job_id}/results. A completed result includes review_complete, locale, pages_read and question rows with source URLs, titles and observation times. Suggestions publish only after all required reviews finish. An empty completed list can be correct when the evidence does not support useful questions. Review and select the rows before adding them to a visibility check.

Review competitor roles

When capabilities include competitors, submit POST /domains/{domain_id}/competitors/estimate with a locale, optional owned source_urls, and up to 100 saved answers. Each answer carries its original UUID id, question, answer, time-zone-qualified observed_at, and public citations with url and optional title.

Console reads the tracked website and cited websites to distinguish competing offerings from reference sources. Citation frequency does not establish authority or competition. These observations remain client-supplied evidence; the operation does not recreate a visibility measurement.

Approve through POST /competitors/jobs using the same reservation fields as content. Read and recover the job through /jobs, then collect GET /competitors/jobs/{job_id}/results. Reviewed websites include their name, domain, role, explanation and original answer_ids. Results publish only when the full review finishes. Select comparison websites explicitly in your client. They are not automatically added to the Console competitor configuration.

Find improvements from saved answers

When capabilities include local_opportunities, send the same saved-answer contract as competitor review to POST /domains/{domain_id}/opportunities/estimate. Console reads the primary website and up to five selected owned pages, reviews the business scope and cited website roles, proposes improvements and checks every proposal against that evidence. This does not rerun the original visibility questions.

Approve through POST /opportunities/jobs. Recover, read and cancel through /jobs, then collect GET /opportunities/jobs/{job_id}/results. Each reviewed opportunity identifies its type (page_update, new_content or site_change), reader benefit, concrete steps, supporting answer_ids and owned source_urls. Page updates and website changes have an editing target_url. New resources have no target URL; their source pages supply context rather than pages to replace. Verify that the suggested resource does not already exist outside the selected page coverage before creating it.

The result includes fresh page excerpts with their own fetched_at timestamps. Retain these separately from older audits and original answers. Recommendations are interpretations, not proof that an edit will cause a ranking change. An empty completed set is valid; failed or incomplete work publishes no proposals.

Check selected questions

Offer this smaller check only when capabilities advertise measurement and the chosen platform in selected_question_platforms. Request POST /domains/{domain_id}/measurement/estimate with 1 to 100 questions, each containing a distinct UUID id and a question of 3 to 500 characters, plus platform, locale and an optional two-letter country.

{
  "questions": [{"id": "c7b2cd7e-44d6-4ba8-9572-c736411df2ef", "question": "How can I share reports with my team?"}],
  "platform": "chatgpt",
  "locale": "en-US",
  "country": "US"
}

Approve through POST /measurement/jobs with the estimate ID, stable UUID request_key and approved_credits. Status, request recovery and cancellation use /jobs. Collect GET /measurement/jobs/{job_id}/results. Each answer keeps its original question ID, wording, platform, locale, time and citation links. The consumer_interface surface identifies scraped interface observations; do not combine them with api observations as interchangeable measurements.

Missing answers have missing_observation, a null answer and no citations. Completed checks include an outcome for every approved question. Failed or cancelled checks can retain fewer outcomes, including an answer received before cancellation. Count these as partial checks, never as absent brand mentions. Read the final receipt before displaying a charge. A lost response or unknown charge is recovered against the original request; it never buys a replacement.

This profile collects fresh answers only. Request competitor review or recommendations separately when needed. Full checks retain their existing price, analysis and supported-platform contract.

Page through evidence

Observations, insights, domain history and check history accept page_size from 1 to 200. Continue using meta.next_cursor until it is null. Cursors are specific to their endpoint and sort order. Keep the same domain, check and filters while paging.

Evidence is scoped to Console-owned domains. Deleted domains and domains or checks belonging to another account cannot be read with your key.