All posts
Tutorial5 min read

ORA field guide: Gift cards

Mert Iseri

This is a field guide for one ORA field: gift_cards. Each field guide answers the same five questions: what the field means, what the agent gets, how the API works for this one field, what is actually being scraped, and how to reproduce it. You need an API key (get one self-serve). Every response shown is a real captured API response.

What the field means

gift_cards reports whether the restaurant itself sells gift cards through a public purchase path, and when the evidence shows it, which commerce platform powers that path. If you sell gift card programs, loyalty, or payments, this field is your install-base map: has_gift_cards: false prospects need the product, has_gift_cards: true prospects have a provider to displace.

What counts: a purchase or balance page the restaurant itself publishes, on its own website or ordering domain, that you can open and verify. What does not qualify: a gift card for the marketplace a restaurant happens to be listed on (an Uber Eats gift card is not a Lou Malnati's gift card), or a third party reselling cards on the restaurant's behalf. The field is about the restaurant's own program.

The value is an object: has_gift_cards (boolean), provider (the platform powering the purchase path, when visible), confidence, a written evidence statement, and evidence URLs.

What the agent gets

The real result for Lou Malnati's Pizzeria in River North, truncated where marked with ...:

{
  "job_id": "d15c0435-7fea-4408-b4d0-481ee6c58bc0",
  "status": "completed",
  "name": "Lou Malnati's Pizzeria",
  "address": "439 N Wells St, Chicago, IL 60654",
  "website": "https://www.loumalnatis.com/chicago-river-north",
  "google_place_id": "ChIJNUoDqLYsDogRG8jygr_J23U",
  "fields": {
    "gift_cards": {
      "status": "completed",
      "value": {
        "evidence": "Official website path leads to WooCommerce with explicit gift-card purchase evidence for Lou Malnati's Pizzeria.",
        "provider": "WooCommerce",
        "confidence": "high",
        ...
        "has_gift_cards": true,
        ...
        "evidence_page_url": "https://www.loumalnatis.com/gift-card-balance/",
        "provider_evidence_url": "https://www.loumalnatis.com/gift-card-balance/"
      },
      "reasoning": "Official website path leads to WooCommerce with explicit gift-card purchase evidence for Lou Malnati's Pizzeria.",
      "evidence_url": "https://www.loumalnatis.com/gift-card-balance/",
      "source_workflow": "gift-cards-v2",
      "error": null
    }
  },
  ...
}

The answer is has_gift_cards: true at high confidence, the purchase path runs on WooCommerce, and the evidence URL is a gift card page on the restaurant's own domain. Open it and check; that is the point of the evidence object.

How the API works for this one field

One job, one field. Create it (this is the only step that spends a credit, 1 per accepted job):

API_KEY=$(cat ~/.cache/248/ora_api_key)
curl -sS -X POST "https://ora.248.ai/v1/enrichment/jobs" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $API_KEY" \
  -d '{
    "name": "Lou Malnati'\''s Pizzeria",
    "address": "439 N Wells St, Chicago, IL 60654",
    "fields": ["gift_cards"],
    "idempotency_key": "blog-2026-07-22-lou-malnatis-gift-cards"
  }'

The real create response:

{
  "job_id": "d15c0435-7fea-4408-b4d0-481ee6c58bc0",
  "status": "pending",
  "requested_fields": [
    "gift_cards"
  ],
  "production_run_id": "d15c0435-7fea-4408-b4d0-481ee6c58bc0",
  "created_at": "2026-07-22T23:46:10.420595Z"
}

Poll the status (free) every 10 seconds until it is completed, failed, or cancelled, then fetch the result (free):

curl -sS "https://ora.248.ai/v1/enrichment/jobs/d15c0435-7fea-4408-b4d0-481ee6c58bc0" \
  -H "X-API-Key: $API_KEY"
curl -sS "https://ora.248.ai/v1/enrichment/jobs/d15c0435-7fea-4408-b4d0-481ee6c58bc0/result" \
  -H "X-API-Key: $API_KEY"

This run took 33 seconds as a fresh enrichment. Inputs are name and address only; ORA resolves the Google listing itself and returns google_place_id as an output.

The failure path is real too. While writing this guide we requested this same field with "name": "Portillo's Hot Dogs" for 100 W Ontario St, and that name did not match the Google listing at that address. The job completed anyway, with the field skipped:

{
  "gift_cards": {
    "status": "skipped",
    "value": null,
    "reasoning": null,
    "source_workflow": "gift-cards-v2",
    "error": "google_match_unmatched"
  }
}

The job was accepted and billed, so unmatched names cost credits. Send the name as it appears on the restaurant's Google listing.

What is actually being scraped

Only public surfaces, and the response names them. In this capture:

  • The restaurant's own website: the evidence_url is a gift card balance page on loumalnatis.com that anyone can open.
  • The purchase path on that page: the response's own evidence statement says the path leads to WooCommerce with explicit gift card purchase evidence, which is how provider gets its value.

If the evidence page does not show what the value claims, do not trust the value. The URL is in the response so you never have to.

How another agent reproduces it

Paste this into Claude Code or Codex. It works in any agent with shell access:

Check whether one restaurant sells gift cards using the ORA API. Host https://ora.248.ai. Auth header X-API-Key on every request; load the key with API_KEY=$(cat ~/.cache/248/ora_api_key) and never print, echo, or commit it. Account and credits endpoints use the /api/v1 prefix; enrichment endpoints use /v1. Free reads: GET /api/v1/account/credits, GET /v1/enrichment/fields, job status, and results. Spending: POST /v1/enrichment/jobs costs 1 credit per accepted job, so create exactly one job.

POST /v1/enrichment/jobs with {"name": "<name as it appears on Google>", "address": "<street address>", "fields": ["gift_cards"], "idempotency_key": "gift-cards-<slug of name and address>"}. Reuse the same idempotency_key on any retry; it returns the existing job instead of billing a new one. Poll GET /v1/enrichment/jobs/{job_id} every 10 seconds until status is completed, failed, or cancelled; a fresh run takes from about half a minute to a few minutes. Then GET /v1/enrichment/jobs/{job_id}/result and save the full response to a file unmodified.

Report from fields.gift_cards: status, value.has_gift_cards, value.provider, value.confidence, the value.evidence statement, and evidence_url. If status is skipped with error google_match_unmatched, the name did not match the Google listing at that address; tell me instead of retrying variations, since each accepted job costs a credit. Never infer a gift card program from the absence of data; report exactly what the field says.

More field guides: POS provider and Menu. For the CSV-scale version of this flow, see the tool guides for Claude Code and Codex.