Endpoints
The full reference for every Operelio API endpoint: the request to send, the response you get back, and every field in it. Single-file and batch.
By Operelio team · Updated July 2026
On this page10
Base URL and how to read this page
Every request goes to the same base URL, over HTTPS, with your API key in the Authorization header:
https://operelio.com/api/v1 Authorization: Bearer op_your_api_key_here
Each endpoint below shows the request to send and the response you get back. The long ids are examples; use the ones your own calls return. For how to build the configJson each tool needs, see the Tools and configJson guide.
POST /uploads
Upload one file so a job can run on it. Send it as multipart form data with the file in a field named "file". Accepts .xlsx, .xls, and .csv. Returns the file's id, which you pass as inputFileId when you create a job.
curl -X POST https://operelio.com/api/v1/uploads \
-H "Authorization: Bearer op_your_api_key_here" \
-F "file=@contacts.csv"
# Response 200
{
"id": "8f3b7a10-2c4d-4e6a-9b1f-0d5c8e2a7f34",
"originalName": "contacts.csv",
"sizeBytes": 12345
}| Field | What it is |
|---|---|
| id | The file's id (a UUID). Pass this as inputFileId when you create a job, or in the fileIds array for a batch. |
| originalName | The filename you uploaded. |
| sizeBytes | The file size in bytes. |
Uploading counts against your plan's file size cap and needs at least one job left in your monthly quota. A file you couldn't process is refused at upload, so nothing sits unused.
POST /jobs
Run one tool on one file. Send JSON with the file's id (inputFileId), the tool to run (toolType), and that tool's settings (configJson). Returns a job id with a status of "queued". The job runs in the background; poll it with GET /jobs/:id.
curl -X POST https://operelio.com/api/v1/jobs \
-H "Authorization: Bearer op_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"inputFileId": "8f3b7a10-2c4d-4e6a-9b1f-0d5c8e2a7f34",
"toolType": "deduplicate",
"configJson": { "columns": ["email"], "keepStrategy": "first" }
}'
# Response 200
{
"id": "3a9c1e57-6b8d-42f0-9a3e-7c1b5d0f2e88",
"toolType": "deduplicate",
"status": "queued",
"createdAt": "2026-07-23T10:00:00.000Z"
}| Send | What it is |
|---|---|
| inputFileId | The id from POST /uploads. Every file tool needs it. |
| toolType | Which tool to run, e.g. "deduplicate". See the Tools and configJson guide for the full list. |
| configJson | The tool's settings. The shape depends on the tool; capture it from the dashboard (see the Tools guide). |
The response status is always "queued" at first. configJson is capped at 100 KB. Sending an unknown toolType returns 400 with the list of valid ones.
GET /jobs/:id
Check a job's status. Call this every couple of seconds until status is "completed" or "failed". While it runs, status moves queued → processing → completed (or failed). When it completes, outputFileId and outputFileName point to the result.
curl https://operelio.com/api/v1/jobs/3a9c1e57-6b8d-42f0-9a3e-7c1b5d0f2e88 \
-H "Authorization: Bearer op_your_api_key_here"
# Response 200
{
"id": "3a9c1e57-6b8d-42f0-9a3e-7c1b5d0f2e88",
"toolType": "deduplicate",
"status": "completed",
"outputFileId": "b2e60d94-1f7a-4c83-8d05-6a9e3b1c7f42",
"outputFileName": "contacts_deduplicated.csv",
"createdAt": "2026-07-23T10:00:00.000Z",
"startedAt": "2026-07-23T10:00:01.000Z",
"finishedAt": "2026-07-23T10:00:04.000Z",
"errorMessage": null
}| Field | What it is |
|---|---|
| status | One of: queued, processing, completed, failed. |
| outputFileId | The result file's id once the job completes. null until then. Pass it to GET /files/:id/download. |
| outputFileName | The result file's name once complete. null until then. |
| createdAt, startedAt, finishedAt | When the job was created, picked up, and finished. startedAt and finishedAt are null until each happens. |
| errorMessage | Why the job failed, when status is "failed". null otherwise. |
A job that failed still returns 200 here, with status "failed" and errorMessage set. That is different from a 4xx or 5xx, which means the request itself didn't reach the job. See Error handling.
GET /files/:id/download
Download a file by its id. Use the outputFileId from a completed job to get the result, or an input file's id to get back what you uploaded. The response is the file itself, not JSON.
curl -O -J https://operelio.com/api/v1/files/b2e60d94-1f7a-4c83-8d05-6a9e3b1c7f42/download \ -H "Authorization: Bearer op_your_api_key_here"
The -O -J flags tell curl to save the file under the name Operelio sends in the Content-Disposition header, instead of printing it to the screen. In your own code, read that header to name the file.
Batch endpoints (Agency)
When you have many files to run through the same tool with the same settings, batch does it in one request instead of one job per file. Batch is on the Agency plan. It supports six tools: Excel to CSV, CSV to Excel, Clean Headers, Health Check, Deduplicate, and Transpose.
One batch counts as a single API call against your rate limit, no matter how many files. An Agency batch takes up to 50 files and 500,000 rows across all of them.
POST /jobs/batch
Create a batch: one tool, one configJson, many files. Upload each file first with POST /uploads, then pass their ids in the fileIds array. Returns a batchId plus ready-made URLs to poll progress and download the combined result.
curl -X POST https://operelio.com/api/v1/jobs/batch \
-H "Authorization: Bearer op_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"fileIds": ["8f3b7a10-...", "1c2d3e4f-...", "9a8b7c6d-..."],
"toolType": "deduplicate",
"configJson": { "columns": ["email"], "keepStrategy": "first" }
}'
# Response 200
{
"batchId": "e7d9c1b2-3a45-4f60-8c17-2b9e0d5a3f18",
"jobIds": ["...", "...", "..."],
"pollUrl": "https://operelio.com/api/v1/jobs/batch/e7d9c1b2-3a45-4f60-8c17-2b9e0d5a3f18",
"downloadUrl": "https://operelio.com/api/v1/jobs/batch/e7d9c1b2-3a45-4f60-8c17-2b9e0d5a3f18/download"
}| Field | What it is |
|---|---|
| batchId | The batch's id. |
| jobIds | One job id per file, in upload order. Each file becomes its own job. |
| pollUrl | A full URL to poll the batch's progress. Use it as-is; you don't have to build it. |
| downloadUrl | A full URL to download every finished file as one ZIP. |
fileIds must be unique. A batch of N files counts as N jobs against your monthly quota, but one call against the rate limit.
GET /jobs/batch/:id
Poll a batch. Returns a progress summary and the status of every job in it. Poll the pollUrl from the create step every couple of seconds until progress shows no jobs still processing.
# Response 200
{
"batchId": "e7d9c1b2-3a45-4f60-8c17-2b9e0d5a3f18",
"toolType": "deduplicate",
"createdAt": "2026-07-23T10:00:00.000Z",
"progress": { "total": 3, "completed": 2, "failed": 0, "processing": 1 },
"jobs": [
{
"id": "...",
"status": "completed",
"inputFile": { "id": "...", "originalName": "list-a.csv" },
"outputFile": { "id": "...", "originalName": "list-a_deduplicated.csv" },
"errorMessage": null
}
]
}| Field | What it is |
|---|---|
| progress.total | How many files are in the batch. |
| progress.completed, failed, processing | Counts by state. Jobs still queued aren't counted in any of these, so early on the three can add up to less than total. |
| jobs[] | One entry per file, with its status, its input and output file, and an errorMessage if it failed. |
GET /jobs/batch/:id/download
Download every successful file in the batch as one ZIP. Call the downloadUrl once the batch has finished. If some files failed, you still get a ZIP of the ones that worked; if every file failed, this returns 400 because there is nothing to download.
curl -O -J https://operelio.com/api/v1/jobs/batch/e7d9c1b2-3a45-4f60-8c17-2b9e0d5a3f18/download \ -H "Authorization: Bearer op_your_api_key_here" # Saves e.g. deduplicate_batch_2026-07-23_e7d9c1.zip
As with single-file downloads, -O -J saves the ZIP under the name in the Content-Disposition header. That name includes the tool, the date, and a short batch code, so two batches never overwrite each other.
Frequently asked questions
Are jobs synchronous or asynchronous?
Asynchronous. POST /jobs returns immediately with a job id; you poll GET /jobs/:id until status is "completed" or "failed". Most jobs finish in under 10 seconds, so a 2-second poll interval is plenty.
What do the ids look like?
Every file, job, and batch id is a UUID, like 8f3b7a10-2c4d-4e6a-9b1f-0d5c8e2a7f34. You never make them up; you read them from one response and pass them to the next call.
How do I know what configJson a tool needs?
That is the one part that changes per tool. The Tools and configJson guide lists every toolType and shows how to capture the exact configJson from the dashboard, so you copy a working shape rather than guess it.
Do API jobs count toward my monthly quota?
Yes. Every job counts as one against your monthly job quota (750 on Team, 2,000 on Agency), the same as running it in the dashboard. A batch of N files counts as N jobs.
Ready to get started?
Upload a file and run your first transformation. Free, no credit card required.