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¶
- Create a profile with
POST /api/v1/search-profile-creations. - Poll profile creation until it returns
SUCCEEDED. - Save the returned
profile_id. - Create an order with
POST /api/v1/orders. - Poll
GET /api/v1/orders/{order_id}while its status is active. - Wait for
status: "COMPLETED"andresults_published: true. - 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}/exportcreates a CSV or XLSX export and returns an output handle:output_id,export_job_id, andstatus.POST /api/v1/orders/{order_id}/outputscreates 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=0lists a bounded output-attempt page withtotalandhas_more.GET /api/v1/orders/{order_id}/outputs/{output_id}reads one output receipt.GET /api/v1/exports/jobs/{export_job_id}/downloaddownloads the finished file once the output isCOMPLETED.
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-Keyon profile creation and order creation. - Retry
429,500,502,503, and504with 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
409as an idempotency conflict and create a new key for the changed request. - Do not fetch results until the order is
COMPLETEDandresults_publishedistrue.
Next Steps¶
- Create your first profile with Search Profile Creation.
- Place a discovery order with Discovery Quick Start.
- Place an enrichment order with Enrichment Quick Start.
- Retrieve every company and interpret email quality with Delivery Integration.
- Recover from failed requests with Error Handling.
- Inspect the exact schemas in the API Reference.