An export writes the companies a saved segment may list — its exportable_count, never its
count — to a CSV, in the background. It is a file job of
operation segment_export: the answer is 202 Accepted with the job, and its URL in
Location; you read it at GET /v1/{country_code}/jobs/{id}
and download it at /jobs/{id}/result or its
download_url, like any job. POST /v1/{country_code}/jobs does not accept this operation.
Only a saved segment can be exported: save it first with save: true.
fields is optional and takes enrich's fields and themes.
Without it the file carries name, legal_form, registered_on, activity, workforce,
size_category and head_office_address. Every export reads each company's head office
whatever fields says, because a company whose head office is partially disclosed is never
written; the head office's columns are in the file only when you select them.
limit is optional too: at most that many rows written, the first in SIREN order rather
than a spread like the sample. A company withheld at writing time does not use up the
limit. Without it, the export writes every company the segment may list. An unknown body
key, a field enrich does not accept, or a limit that is not a whole number of 1 or more
is 400 invalid_request.
Submit, wait, download
The block sets the key, submits segment 1, then reads the job until it is final and stops
on any refusal, which curl -f turns into an empty $JOB rather than a loop that never
ends:
read -rs FIRMUS_KEY && export FIRMUS_KEY
JOB_URL=$(curl -s -o job.json -w '%header{location}' -X POST \
-H "Authorization: Bearer $FIRMUS_KEY" \
-H "Content-Type: application/json" \
-d '{}' \
https://api.firmus.sh/v1/fr/segments/1/export)
cat job.json
while JOB=$(curl -sf -H "Authorization: Bearer $FIRMUS_KEY" "$JOB_URL") &&
! printf '%s' "$JOB" | grep -Eq '"status":"(succeeded|failed)"'; do
sleep 5
done
printf '%s\n' "$JOB"
curl -sf -H "Authorization: Bearer $FIRMUS_KEY" -o segment.csv "$JOB_URL/result"A refused submission has no Location, so $JOB_URL is empty and job.json holds the
error. The job carries what a file job carries, and three things more:
counts.segment_export:exported, the rows written;withheld, companies that became partially disclosed (the company or its head office) or a sole trader since the count, or whose record could not be read in full, and so were not written;not_found, companies gone from the registry since the count.exported_rows, what the job has counted against the month's exported rows so far. A withheld or not-found company is not counted.agent_rowsstays at0: an export spends no agent rows.segment, the segment as it was when the export was admitted —id,name,filters,as_of(the day its windows counted from),include_sole_traders,acknowledgement(with thetextof its version),limit(nullwithout one) — andnotice, the RNE caveat. Deleting or replacing the saved segment does not change a file being written.
progress.total_rows is what the export was admitted for — the exportable_count, or the
limit when it is smaller — and processed_rows the companies read so far; exported can
end below total_rows, never above it. An export never writes or counts more rows than it
was admitted for: companies that join the segment after admission wait for the next export.
The file
UTF-8 with a byte-order mark, comma-separated, named segment-{id}-firmus.csv. It does not
start with its header. The first lines are notices, one cell each, starting with #:
- the RNE caveat: segments are built from INSEE Sirene and do not reflect an opposition to prospecting recorded only in the RNE;
- the segment, its filters and the day its windows counted from;
- on a segment saved with sole traders only, the acknowledgement, its version, who gave it and when.
Then the header and one line per company. Skip the lines that start with # before handing
the file to a CSV reader or a CRM import, or the first notice becomes your header. The
columns are firmus_registry_number, firmus_enrich_status, the columns of the selected
fields as a file job that enriches writes them, firmus_data_updated_at (the registry's
timestamp for the record, not an import time), firmus_enrich_message, firmus_partial,
firmus_partially_disclosed and firmus_sources. firmus_partially_disclosed is always
false, since such a unit is never written; the column says so in the file that reaches the
CRM. A cell a spreadsheet would run as a formula is written behind a leading apostrophe, as
in every job result.
The job, its result and its download_url are kept seven days, until expires_at, then are
404.
Exported rows
The export is checked up front, for the whole segment: its exportable_count today, or
the limit when it is smaller, must fit in the month's exported rows left, counting as
spent what your organization's unfinished exports were admitted for. The month holds 1 000 exported rows on Free, 25 000 on
Pro and 250 000 on Scale, on a meter of their own: exports do not spend agent rows, and file
jobs do not spend exported rows. A segment that does not fit is refused and no job is
created; message gives the rows left, which is the largest limit that would be admitted:
{
"error": {
"status": 402,
"code": "quota_exceeded",
"message": "This export would write up to 1840 rows, and this organization has 1000 exported rows left this month. Send `limit` (at most 1000) to export the first rows, in SIREN order, narrow the segment, or wait for the allowance to reset at the start of the next calendar month, UTC.",
"documentation_url": "https://docs.firmus.sh/reference/errors#quota_exceeded"
}
}Retry-After counts the seconds to the start of the next calendar month, UTC. Only the rows
written are counted. Submitting is one call — on Free, one of the month's 1 000 lookups;
reading the job and downloading the file are not calls.
Errors
400 invalid_request— an unknown body key, a fieldenrichdoes not accept, or alimitthat is not a whole number of 1 or more.402 quota_exceeded— the segment, or itslimit, does not fit in the month's exported rows, as above, or on Free the month's lookups are spent. Both carryRetry-After.403 public_key_forbidden— a publishablefk_pubkey holdingread.404 not_found— a segment that is not one of your organization's, or a country other thanfr.503 segment_index_unavailable— this server cannot count segments yet; no job is created.