Skip to content

Supplier API

The Supplier API exposes Speci-finder matched project results for a supplier user.

Open the live API reference

GET /api/supplier/v1/companies/{companyId}/speci-finder/results
RequirementValue
Scopespeci-finder/read
HeadersAuthorization: Bearer <access_token>, x-e1-client-id: <client_id>
NameTypeDescription
companyIdstringE1 company identifier for the supplier. Must match a registration on your application.

Both are optional. Selection of “currently open” tenders is scoped server-side; these parameters only control paging.

NameTypeDescription
cursorstringOpaque pagination cursor. Pass the _metadata.nextCursor value from a previous response to fetch the following page. Omit on the first request. Treat it as opaque — do not construct or parse it.
limitintegerPage size. Defaults to 25; must be between 1 and 100. An out-of-range or non-numeric value returns 400.

Returns one page of matched projects, each with one or more matched tenders, plus a _metadata object describing the page. A project appears once per response; if a single project has matched tenders under different builders, those tenders are grouped under the same project entry.

{
"data": [
{
"projectId": "12345",
"projectName": "Main Street Development",
"address": "123 Collins St, Melbourne Victoria 3000 Australia",
"category": "Commercial",
"budget": { "low": 1000000, "high": 5000000 },
"status": "Active",
"consultants": [
{ "name": "Smith Engineers", "website": "https://smith.example" },
{ "name": "Jones Architects", "website": null }
],
"tenders": [
{
"id": "67890",
"name": "Bulk Earthworks",
"type": "Tender",
"builder": { "name": "ABC Constructions", "website": "https://abc.example" },
"tenderOpenAt": "2026-05-01",
"quotesDueAt": "2026-05-15",
"status": "Open",
"matchedKeywords": ["concrete", "formwork"]
}
],
"tenderingSubcontractors": [
{ "name": "Apex Concrete", "website": "https://apex.example" },
{ "name": "Pour & Set", "website": null }
],
"url": "https://app.estimateone.com/find-tenders?projectId=12345"
}
],
"_metadata": {
"nextCursor": "MjAyNi0wNS0xNXwxMjM0NQ",
"hasNextPage": true
}
}

Project

FieldTypeNotes
projectIdstringE1 project identifier.
projectNamestringHuman-readable project name.
addressstringFull international postal address (street, suburb, state, postcode, country).
categorystringProject category (e.g. Commercial, Residential).
budget{ low: number, high: number | null } | nullBanded budget range in dollars. null when no budget is set; high may be null for an open-ended top end.
status"Active" | "Closed"Project-level status. Closed indicates the project itself is closed (regardless of any individual tender status).
consultantsarray of PartyConsultants engaged on the project. Empty for partners without the consultant-details add-on. Excludes unverified entries.
tendersarray of TenderOne or more matching tenders. Never empty for a returned project.
tenderingSubcontractorsarray of PartySubcontractors who have responded affirmatively to the builder on this project (currently quoting / quoted / quoted outside E1, or signalled interest via watchlist). Subject to the E1 SubbieSupplierConnection unlock model — for projects you haven’t unlocked, this lists only previously-viewed subbies. Deduplicated by company.
urlstringDeep link into the E1 web app for this project.

Tender

FieldTypeNotes
idstringE1 tender identifier.
namestringTender name (typically a trade package, e.g. “Bulk Earthworks”).
type"Tender" | "Procurement"Which product surface the tender belongs to.
builderPartyThe lead builder running this tender.
tenderOpenAtISO 8601 date (YYYY-MM-DD) or nullWhen the tender opened.
quotesDueAtISO 8601 date (YYYY-MM-DD) or nullWhen quotes close. null if no due date is set.
status"Open" | "Closed" | "Awarded"Tender-level status.
matchedKeywordsarray of stringThe subset of the supplier account’s Speci-finder keywords that matched this tender.

Party

FieldTypeNotes
namestringDisplay name of the company (preferring the linked E1 account’s name when available).
websitestring | nullCompany website URL, normalised to include an https:// scheme. null when no website is on file.

_metadata

FieldTypeNotes
nextCursorstring | nullPass as the cursor query parameter to fetch the next page. null when there are no more pages.
hasNextPagebooleantrue when another page is available. Equivalent to nextCursor !== null.

Results are paged with an opaque cursor, ordered by each project’s earliest tender quotesDueAt (ascending, undated projects last). To walk every page:

  1. Make the first request with no cursor (optionally set limit).
  2. If _metadata.hasNextPage is true, repeat the request with cursor set to _metadata.nextCursor, keeping the same limit.
  3. Stop when hasNextPage is false (nextCursor is null).

The cursor encodes a position in the ordering, so pages never overlap or skip entries even as limit varies between requests. Treat the cursor as opaque — its contents are not part of the contract. Re-requesting the same cursor/limit within a short window is served from cache, so a paged sweep stays cheap and stable.

  • Results only include tenders that are currently open — quotes are not past due and fall within the near-term window. The window is server-side; partners do not control it.
  • Matching is driven by the supplier account’s Speci-finder keywords (account-wide; resolved via the assigned user on the credential). If the account has no keywords configured, the response will be 200 OK with data: [].
  • See Data freshness for how quickly new data propagates.

First page (default limit):

Terminal window
curl -X GET \
"https://api.estimateone.com/api/supplier/v1/companies/{companyId}/speci-finder/results?limit=25" \
-H "Authorization: Bearer $TOKEN" \
-H "x-e1-client-id: $CLIENT_ID"

Next page — pass the previous response’s _metadata.nextCursor:

Terminal window
curl -X GET \
"https://api.estimateone.com/api/supplier/v1/companies/{companyId}/speci-finder/results?limit=25&cursor=MjAyNi0wNS0xNXwxMjM0NQ" \
-H "Authorization: Bearer $TOKEN" \
-H "x-e1-client-id: $CLIENT_ID"

See Errors for the full catalogue. Common failures for this endpoint:

StatuscodeCause
400CLIENT_ID_HEADER_MISSINGx-e1-client-id header not sent.
401CLIENT_ID_HEADER_MISMATCHx-e1-client-id header does not match the token.
401UnauthorisedToken invalid, company not registered, permission not published, or scope missing.
5xxFETCH_FAILED / INTERNAL_SERVER_ERRORSomething failed downstream. Retry with backoff.

The full OpenAPI 3.1 spec is published at https://api.estimateone.com/swagger/doc. Use it to drive client code generation in the language of your choice. You can also browse it interactively.