Skip to content

Orders Overview

Use orders when you want OpenProspect to deliver company briefings. Every order starts from a search profile.

Mental Model

Concept Meaning
Search profile What to look for and how to qualify companies
Order What you want OpenProspect to deliver now
Discovery order Find new qualified companies for a profile
Enrichment order Enrich companies you already provide
briefing_quantity Number of companies requested or submitted
available_briefing_quantity Number of companies in the published result set
results_published Whether the immutable order result set exists, including a valid zero-result set

Create the profile first, then place one or more orders from that profile.

Choose a Flow

You have Use Send companies? Send briefing_quantity?
An ICP and need new companies Discovery No Yes
A list of companies to enrich Enrichment Yes No

For discovery, briefing_quantity is the number of qualified companies you want delivered. For enrichment, the API derives briefing_quantity from companies.length because submitted companies are treated as prequalified.

Basic Flow

  1. Create a profile with POST /api/v1/search-profile-creations.
  2. Poll profile creation until it returns SUCCEEDED.
  3. Save the returned profile_id.
  4. Create an order with POST /api/v1/orders.
  5. Poll GET /api/v1/orders/{order_id} while its status is active.
  6. Wait for status: "COMPLETED" and results_published: true.
  7. Fetch every page from GET /api/v1/orders/{order_id}/results.

External clients submit orders, poll status, and retrieve completed results. OpenProspect performs review and managed fulfillment internally. Clients do not call admin endpoints or run individual enrichment features themselves.

Statuses

Profile creation has a small async lifecycle:

Status Meaning Next step
PENDING The request is queued Poll again
RUNNING The profile is being created Poll again
SUCCEEDED The profile is ready Create an order
FAILED Profile creation did not finish Retry with a new idempotency key

Orders use this lifecycle:

Status Class Meaning Next step
RECEIVED Active The API accepted the order for review; companies are not enriched yet Poll again
ACCEPTED Active OpenProspect approved the order for managed fulfillment; requested features are not necessarily ready. Fulfillment starts at acceptance, so a poll normally observes IN_PROGRESS directly Poll again
IN_PROGRESS Active OpenProspect is producing the requested results Poll again
COMPLETED Successful terminal Managed fulfillment ended Fetch results when results_published is true
REJECTED Unsuccessful terminal The order was not approved Stop polling and contact support with the order ID
FAILED Unsuccessful terminal Fulfillment failed Stop polling and contact support with the order ID
CANCELLED Unsuccessful terminal The order was cancelled Stop polling

Poll only while the status is RECEIVED, ACCEPTED, or IN_PROGRESS. Stop on COMPLETED, REJECTED, FAILED, or CANCELLED.

Result Publication And Counts

OpenProspect publishes one immutable result set for a successful order. Each result item is one slot:

Field Meaning
input_position Zero-based position of the submitted row (enrichment) or of the found company (discovery)
external_id The external_id you submitted for this row, when provided
status ENRICHED, PARTIAL, UNRESOLVED, DUPLICATE, or BLOCKED
reason_codes Stable machine-readable reasons for the status
reasons The same reasons with an English message and, where known, a detail you can act on (see Result reasons)
duplicate_of_input_position Earlier row this slot resolved to the same company as
company The enriched company with embedded prospects, or null when the identity never resolved

Every results page also carries a summary, and the order status carries the same object as result_summary once results_published is true:

Field Meaning
requested_count Rows submitted (enrichment) or briefings requested (discovery)
fully_enriched_count Slots delivered as ENRICHED
annotated_count Slots returned with a reason instead (PARTIAL, UNRESOLVED, DUPLICATE, BLOCKED)
reasons code, message, a short label for counts ("no email found"), and count per reason for the annotated slots. Discovery results contain only the companies that were delivered, so a discovery summary lists no reasons

Enrichment orders return every submitted row in submitted order. The profile's delivery policy is evaluated at publication time and annotates each row; it never removes one. A row that could not be fully enriched is returned with status: "PARTIAL", its company facts, and the reason — and no selected contacts. An enrichment order with 498 submitted companies therefore has total and available_briefing_quantity of 498; filter on status == "ENRICHED" if you only want policy-eligible companies.

Result reasons

A reason names the first stage that stopped for that row. The code is the stable contract; the message is English wording that may improve between releases; detail is present only when there is a fact behind the reason.

code Applies to Meaning detail
POLICY_ELIGIBLE ENRICHED Fully enriched and eligible under the profile's delivery policy —
HISTORICAL_DELIVERY_CONFIRMED ENRICHED Delivered before results became immutable; the historical delivery was confirmed (legacy orders only) —
HISTORICAL_POLICY_EXCLUDED PARTIAL Excluded by the delivery policy before results became immutable (legacy orders only) —
WEBSITE_UNREACHABLE PARTIAL The website could not be reached (DNS, TLS, connection or timeout) The URL that was tried
WEBSITE_MOVED PARTIAL The website redirects to a domain that is not the company's own site (a parking page, registrar, directory or messenger) or that blocks automated access; a site that moved to the company's new domain is followed The origin it redirects to
WEBSITE_BLOCKED PARTIAL The website blocked automated access —
WEBSITE_EMPTY PARTIAL The website returned no usable content —
NO_PEOPLE_FOUND PARTIAL The website was read, but no people were found on it —
NO_EMAIL_FOUND PARTIAL People were found, but no email address could be discovered —
NOT_PROCESSED PARTIAL OpenProspect did not finish processing this row; contact support with the order ID if it matters to you —
REQUIRED_CONTACT_PATH_MISSING PARTIAL Contacts were found, but none offers the contact path the profile requires —
COMPANY_SCORE_BELOW_MINIMUM PARTIAL The company's fit score is below the profile's minimum —
PROSPECT_SCORE_BELOW_MINIMUM PARTIAL No contact reached the profile's minimum qualification score —
UNRESOLVED_IDENTITY UNRESOLVED The submitted company could not be matched to a website or organisation —
DUPLICATE_OF_SLOT DUPLICATE The same company was submitted in an earlier row —
BLOCKED_FOR_REVIEW BLOCKED Held back for operator review —
RESULT_LIMIT_EXCEEDED discovery only Eligible, but outside the requested quantity —

Rows that report WEBSITE_UNREACHABLE, WEBSITE_MOVED, WEBSITE_EMPTY or UNRESOLVED_IDENTITY are usually fixed on your side: correct the URL in your list and submit those rows again in a new order.

Discovery orders return the companies the order found, each with status: "ENRICHED"; available_briefing_quantity is the published count.

briefing_quantity is the requested or submitted population. A valid publication can contain zero results, so use results_published, not a positive count, to decide whether the result resource exists.

For orders created before immutable publication was introduced, a historical record can be COMPLETED while results_published is false. In that case, GET /api/v1/orders/{order_id}/results returns ORDER_RESULTS_NOT_READY; contact support with the order ID rather than reading profile-wide company inventory.

Order Results Versus Profile Inventory

Use GET /api/v1/orders/{order_id}/results as the source of truth for one order. Its pages are a stable snapshot and contain only that order's published companies.

GET /api/v1/deliveries/{prospect_search_id}/companies is legacy profile-wide CRM sync / drip. It can include companies from older or unrelated orders for the same profile and must not be used to reconcile an order. That collection will leave the public API-key contract in a later version. For enrichment orders, a submitted external_id is returned as the company-level source_id, providing the exact round-trip key for your CRM or batch input.

Result pages default to 50 slots and accept at most 100. Start at offset=0, increase offset by the number of returned items, and continue until has_more is false.

Optional Outputs

The order-results API is the primary delivery contract. Optional CSV, XLSX, and Google Sheets outputs are projections of the same immutable result set; they do not select a different company population and cannot change order completion.

  • POST /api/v1/orders/{order_id}/export creates a CSV or XLSX export and returns an output handle: output_id, export_job_id, and status.
  • POST /api/v1/orders/{order_id}/outputs creates a durable file or Google Sheets output and returns the same handle (plus explicit idempotency).
  • GET /api/v1/orders/{order_id}/outputs?limit=50&offset=0 lists a bounded output-attempt page with total and has_more.
  • GET /api/v1/orders/{order_id}/outputs/{output_id} reads one output receipt.
  • GET /api/v1/exports/jobs/{export_job_id}/download downloads the finished file once the output is COMPLETED.

Output creation is asynchronous. Both POST .../export and POST .../outputs return immediately with the handle above; poll GET /api/v1/orders/{order_id}/outputs/{output_id} until status is COMPLETED or FAILED, then download a completed file from GET /api/v1/exports/jobs/{export_job_id}/download. A failed optional output does not remove or rewrite the published API results. A published zero-result order is valid through the results API but has nothing to project; output creation returns 409 / ORDER_RESULTS_EMPTY.

Create an output only after results_published is true:

curl --fail-with-body -sS -X POST \
  "https://api.openprospect.io/api/v1/orders/${ORDER_ID}/outputs" \
  -H "Authorization: Bearer ${OPENPROSPECT_API_KEY}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: ${ORDER_OUTPUT_IDEMPOTENCY_KEY}" \
  -d '{"output_type":"xlsx","output_language":"en"}'

Supported output_type values are csv, xlsx, and google_sheets. Google Sheets also requires spreadsheet_id.

Persist one output idempotency key before the first request and retry an uncertain response with the same key and identical body. Each result-set destination is one logical output. Omitting the Idempotency-Key header binds the output to a server-derived key that the response discloses as idempotency_key; requests without a key always replay the existing output for that destination. The created field distinguishes a fresh dispatch from an idempotent replay. 409 / OUTPUT_IDEMPOTENCY_CONFLICT occurs only when two different explicit keys claim the same destination; retry with the original key, or omit the header to replay. A different destination is a separate logical output.

Each published order accepts at most 20 logical outputs. Further new destinations return 409 / OUTPUT_QUOTA_EXCEEDED; poll or retry an existing output instead.

The response includes output_id, created, status, result_count, result_sha256, export_job_id, and transport receipt fields. Poll GET /api/v1/orders/{order_id}/outputs/{output_id}. Treat COMPLETED as success and FAILED as an output-specific failure; in either case the primary order results remain available through the API.

Retrieve a finished CSV or XLSX file through the export download endpoint using the output's export_job_id:

curl --fail-with-body -sS -L \
  "https://api.openprospect.io/api/v1/exports/jobs/${EXPORT_JOB_ID}/download" \
  -H "Authorization: Bearer ${OPENPROSPECT_API_KEY}" \
  -o order-results.zip

Google Sheets outputs report the spreadsheet URL in the receipt's location field instead; there is no file to download.

What to Store

Store these IDs in your system:

ID Why
profile_creation_id Poll profile creation and debug failed synthesis
profile_id Reuse the same profile for discovery and enrichment orders
order_id Poll order status and fetch delivered results
Your idempotency keys Retry safely without creating duplicates

If you send external_id for enrichment companies, store it too. Results return that value as source_id.

Reliability Rules

  • Send Idempotency-Key on profile creation and order creation.
  • Retry 429, 500, 502, 503, and 504 with backoff.
  • Retry POST requests with the same idempotency key only when the body is the same.
  • Use a new idempotency key when you intentionally change the request body.
  • Treat 409 as an idempotency conflict and create a new key for the changed request.
  • Do not fetch results until the order is COMPLETED and results_published is true.

Next Steps