Skip to main content

Asynchronous processing

The API is built for partners sending large volumes, so the bulk endpoints do not process your request while you wait. They accept it, queue it, and hand you a correlation id. You poll that id until the work is finished, then read the result.

Every import and search under /bulk/ works this way. The task endpoints below and the reference-data endpoints — frameworks, groups, unit types, custom properties — answer immediately and are not part of the queue.

The loop

1. Submit. Send your payload to a bulk endpoint. The response carries a correlation id.

curl -X POST https://api.because.eco/api/v1/bulk/company-mappings \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d @mappings.json

2. Poll. Ask the task endpoint for that correlation id until it reports a terminal state — the same endpoint whatever you submitted, v1 or v2.

curl https://api.because.eco/api/v2/bulk/tasks/{correlationId} \
-H "Authorization: YOUR_API_KEY"

3. Read the result. Once the task is finished, its response carries the outcome. The bulk searches deliver a list of page URLs to download; the calculators upsert and company mappings deliver a single file entry whose URL is the complete result — Result files describes what is in every one of those files. The remaining imports deliver no file: the task reports status and, on failure, what went wrong, row by row where the endpoint supports it.

Poll on an interval rather than in a tight loop. How long a request takes scales with how much you sent.

Two more task endpoints round this out: GET /api/v2/bulk/tasks lists your newest tasks with their statuses, and a task that has not started processing yet can be cancelled.

Or skip the polling: a webhook can push each status change to an endpoint of yours instead.

Ordering: what is and is not guaranteed

Requests submitted with the same API key are picked up in the order you sent them. They are not guaranteed to finish in that order, because several run in parallel and a small request submitted second can easily overtake a large one submitted first.

This distinction matters when one request depends on another. If you upsert companies and then upsert performance answers against those companies, do not submit both and assume the first completes first. Wait for the first to reach a terminal state before submitting the second.

Payload size

There is no hard limit on payload size, but requests are more likely to succeed, and far easier to diagnose, when they are split. For company mappings, keep a single request under 100,000 companies.

Splitting also gives you finer-grained failure handling: one oversized request that fails tells you very little, whereas ten smaller ones tell you which slice of your data is the problem.

Reading outcomes

A request reaching a terminal state means processing finished — not that every item succeeded. Bulk results report per-item outcomes, and items can fail individually for reasons that are not errors in your request: a company your key's profile cannot access, an identifier that matches nothing, a value outside an allowed list.

Read the per-item results. A request that reports success overall can still have skipped rows you care about. For a search they are in the result files; for an import that delivers no file, the failed rows are under the task's error, and the full row-level record — successes included — is in the BeCause app under Company manager → Import & export → API → API usage, as a downloadable report per request.