Understand Responses

Check the response envelope first, then read only the fields your operation requested.

Immediate Response Envelope

Example
{
  "success": true,
  "data": {
    "markdown": "# Example Domain...",
    "links": ["https://www.iana.org/domains/example"],
    "metadata": {
      "title": "Example Domain",
      "source_url": "https://example.com",
      "status_code": 200,
      "word_count": 28,
      "content_length": 191
    }
  },
  "job_id": "optional-job-id",
  "time_taken": 1.42
}
FieldMeaningHandling rule
successWhether the requested operation produced a successful public resultCheck it before reading data
dataReturned content or structured recordsTreat fields as conditional on operation and requested formats
errorHuman-readable failure contextLog safely and show a user-appropriate message
error_codeMachine-readable failure category when availableUse it to select retry or recovery behavior
job_idIdentifier for persisted or asynchronous workStore it with your internal operation record
time_takenPublic elapsed time in seconds when availableUse for observability, not as a fixed performance guarantee

Data Fields Are Format-Driven

Optional fields are omitted when they were not requested or produced.

Requested format or featureExpected fieldNotes
markdowndata.markdownReadable normalized content
htmldata.htmlNormalized HTML
raw_htmldata.raw_htmlPotentially large source-oriented HTML
linksdata.links and possibly data.links_detailURL list plus richer link grouping when available
imagesdata.imagesImage records can include source and descriptive metadata
headingsdata.headingsDocument outline information
structured_datadata.structured_dataEmbedded page metadata such as JSON-LD or Open Graph
screenshotdata.screenshotLarge encoded visual output
LLM extractiondata.extractValidate important values against source content

Metadata Describes the Source

FieldUse
titleDisplay name or document title
descriptionPage-provided summary when available
languageLanguage information when identified
source_urlThe source associated with the returned content
status_codeSource response status represented in the result
content_typeReturned source media type when available
word_countApproximate text volume
reading_time_secondsApproximate reading duration
content_lengthReturned content size measurement
canonical_urlCanonical source declared by the page when available
og_imagePrimary social image when declared
faviconPage or site icon when available

Inspect a Response With jq

Example
# Save the complete response
curl --fail-with-body --silent --show-error \
  -X POST "https://api.datablue.dev/v1/scrape" \
  -H "Authorization: Bearer $DATABLUE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "formats": ["markdown", "links", "images"]
  }' > response.json

# Summarize without printing the full content
jq '{
  success,
  error,
  error_code,
  time_taken,
  source: .data.metadata.source_url,
  status: .data.metadata.status_code,
  words: .data.metadata.word_count,
  markdown_chars: (.data.markdown | length),
  links: (.data.links | length),
  images: (.data.images | length)
}' response.json

Asynchronous Job Lifecycle

Crawl, Search, and multi-source Extract can return jobs. Store the job and follow its lifecycle.

  1. Start: send the operation request and store the returned job_id.
  2. Observe: poll the operation status endpoint or subscribe to the documented event flow.
  3. Read partial progress: when supported, display completed counts and available result rows.
  4. Stop on a terminal state: completed, failed, or cancelled.
  5. Persist the outcome: store source URLs, result identifiers, and the final status needed by your product.

Start a crawl and capture its id

Example
export CRAWL_JOB_ID="$(
  curl --fail-with-body --silent --show-error \
    -X POST "https://api.datablue.dev/v1/crawl" \
    -H "Authorization: Bearer $DATABLUE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://example.com",
      "max_pages": 10,
      "max_depth": 2,
      "concurrency": 2,
      "scrape_options": {
        "formats": ["markdown", "links"]
      }
    }' | jq -r '.job_id'
)"

echo "$CRAWL_JOB_ID"

Poll status and page through results

Example
curl --fail-with-body --silent --show-error \
  "https://api.datablue.dev/v1/crawl/$CRAWL_JOB_ID?page=1&per_page=20" \
  -H "Authorization: Bearer $DATABLUE_API_KEY" | jq '{
    status,
    total_pages,
    completed_pages,
    total_results,
    page,
    per_page,
    returned_rows: (.data | length),
    error
  }'

Poll until a terminal state

Example
while true; do
  RESPONSE="$(
    curl --fail-with-body --silent --show-error \
      "https://api.datablue.dev/v1/crawl/$CRAWL_JOB_ID?page=1&per_page=20" \
      -H "Authorization: Bearer $DATABLUE_API_KEY"
  )"

  STATUS="$(printf '%s' "$RESPONSE" | jq -r '.status')"
  printf '%s
' "$RESPONSE" | jq '{
    status,
    completed_pages,
    total_pages,
    error
  }'

  case "$STATUS" in
    completed) break ;;
    failed|cancelled) exit 1 ;;
    *) sleep 2 ;;
  esac
done

Cancel work that is no longer needed

Example
curl --fail-with-body --silent --show-error \
  -X DELETE "https://api.datablue.dev/v1/crawl/$CRAWL_JOB_ID" \
  -H "Authorization: Bearer $DATABLUE_API_KEY" | jq .

Pages completed before cancellation can remain available. Treat cancellation as a terminal state with potentially useful partial results.

Failure Envelope

Example
{
  "success": false,
  "data": null,
  "error": "Human-readable failure context",
  "error_code": "TIMEOUT",
  "job_id": "optional-job-id",
  "time_taken": 30.0
}

Separate HTTP failure from operation failure

  • HTTP status: tells you whether authentication, validation, admission, or routing succeeded.
  • success: tells you whether DataBlue produced the requested public result.
  • status: tells you where an asynchronous job is in its lifecycle.
  • error_code: helps select a recovery path when the response provides one.
  • error: provides context for logs and user-facing translation.

Defensive Parsing Rules

  1. Parse the HTTP response body even when the status is not 2xx.
  2. Check success before dereferencing data.
  3. Expect optional fields to be absent.
  4. Validate arrays before assuming they contain rows.
  5. Store job_id before beginning polling.
  6. Keep original source URLs beside transformed or extracted data.
  7. Do not treat elapsed time or word count as a completeness guarantee.
  8. Validate high-impact extracted facts against source evidence.

Next Step

Use Production Readiness to turn this response model into retry, timeout, webhook, storage, and observability policies.