Qualification API

Manage qualification prompts, preview costs, and run workspace jobs.

Authentication and scope

Use a Lightmeter organization API key for the intended workspace. Every template, estimate, and job operation uses that workspace. IDs from another workspace return not found. Prompt writes and cost previews do not start paid qualification work; the job start endpoint does.

Base URL: https://beam.lightmeter.io/api/v1. Qualification JSON writes have a 128 KiB limit; larger bodies return 413.

Prompt templates

MethodPathResult
GET/qualification/prompt-templates{"templates": [...]}, ordered with the default first, then name.
GET/qualification/prompt-templates/defaultDefault template, or 404 when none exists.
GET/qualification/prompt-templates/{id}One template, or 404.
POST/qualification/prompt-templatesCreate a template; 201. A duplicate name in the workspace returns 409.
PUT/qualification/prompt-templates/{id}Replace the template fields; 200. Supply all required fields, including optional_threshold and is_default.
POST/qualification/prompt-templates/{id}/set-defaultSet that template as the workspace default; 200.
DELETE/qualification/prompt-templates/{id}Delete a nondefault template; 200. Delete the default returns 400; select another default first.

Creation and replacement use the same full template shape as the Beam editor: name, optional description, introduction, target_icp, a nonempty questions array, output_format, optional_threshold from 0 to 100, and is_default. Questions contain id, label, question, signal_proxies, min_accuracy, required, polarity, and max_reasoning_words. Output format contains instructions and include_reasoning.

{
  "name": "Prospect fit",
  "introduction": "Research the company using public signals.",
  "target_icp": "B2B software companies",
  "questions": [{
    "id": "fit", "label": "Fit", "question": "Does the company fit?",
    "signal_proxies": ["company website"], "min_accuracy": 80,
    "required": true, "polarity": "positive", "max_reasoning_words": 30
  }],
  "output_format": {"instructions": "Answer briefly", "include_reasoning": true},
  "optional_threshold": 50,
  "is_default": false
}

Read-only cost estimate

POST /qualification/estimate accepts a saved template_name and 1 to 250 companies. Each company needs a name and may include a domain. The response matches the Beam qualification preview: summary counts, previously processed details, and processing options with estimated USD cost. The estimate looks up existing workspace companies and cached qualification results; it does not create company rows, persist results, or start a paid job. Costs are estimates, not a purchase or spend authorization.

{"template_name":"Prospect fit","companies":[{"name":"Example","domain":"example.com"}]}

A missing template returns 404. Both the public API and MCP accept at most 250 companies per call. See MCP documentation for the OAuth tool names.

Qualification jobs

Call POST /qualification/estimate before starting a job. Then send POST /qualification/jobs with 1 to 250 companies, a saved template name, a processing mode, a caller-generated operation_id UUID, and max_cost_usd. The server rejects a request whose current estimated cost exceeds that ceiling or the workspace credit limit. Starting a job can incur provider charges. Each workspace may have one accepted, running, or interrupted job at a time; another operation returns 409 until that job reaches a terminal state. Reuse the same operation ID and identical body when retrying; the response returns the same job ID and original estimate without starting another job. A changed body with the same operation ID returns 409.

{"operation_id":"d6d91a65-7e97-4cdd-8ec4-f9a72d331cef","template_name":"Prospect fit","processing_mode":"process_new_only","max_cost_usd":5,"companies":[{"name":"Example","domain":"example.com"}]}

The accepted response is {"id":"...","estimated_cost_usd":0.25} with status 202. The estimate is a reservation basis, not a guarantee of the final provider charge. processing_mode accepts process_new_only, process_all_with_new_criteria, reprocess_same_criteria, or process_all.

MethodPathResult
GET/qualification/jobs?limit=50Recent API or MCP jobs in the workspace, up to 100, with durable lifecycle status.
GET/qualification/jobs/{id}/progressPending, running, completed, failed, cancelled, or interrupted. A stale accepted job fails with its reserved credit released. An interrupted running job retains its reservation pending operator reconciliation.
POST/qualification/jobs/{id}/cancelCancel an accepted job before provider work and release its reservation, or persist a running job's cancellation request.
GET/qualification/jobs/{id}/resultsStored JSON results when available, including partial results from a failed or cancelled job.
GET/qualification/jobs/{id}/exportCSV attachment of stored results.

Only jobs started through the API or MCP appear here. Results and export return 404 until a result is stored. Provider diagnostics are replaced with safe customer-facing error messages in both formats. Retrying an interrupted job with the same operation ID returns its existing ID and never replays provider work; use a new operation ID only after reviewing the retained charge and any partial results.

Endpoint reference