The request
Reference for Rehearse import, HeadHoncho API v1. It is a command, sent to the base address https://api.headhoncho.app.
POST /api/v1/commands/rehearse-import
The key needs the Jobs area at read. An answered call costs 1 credit; a refusal costs nothing. See credits.
It runs the app's own command rehearse-import. Send an Idempotency-Key header with every call: the same key with the same body returns the first answer and runs nothing twice. See the model.
Parameters
| Name | Kind | Required | Description | Example |
|---|---|---|---|---|
company_id | id, in the JSON body | Yes | The company the jobs land in. From Who am I. | cmp_14f5 |
plan | text, in the JSON body | Yes | The staged files as a JSON list. Each item: staging_id (from Stage an import file), half (jobs, money or payments), mapping (field to column numbers) and date_order. | [{"staging_id": "k3Zp...", "half": "jobs", "mapping": {"ref": [0], "client_name": [1]}}] |
status_map | object, in the JSON body | No | The file's status word to a target, from Map statuses. | {"Done": "st_06"} |
type_map | object, in the JSON body | No | The file's job-type word to a target, from Map job types. | {"Local Move": "jt_02"} |
worker_map | object, in the JSON body | No | The file's technician name to one of our worker ids, or null to leave that technician's jobs unassigned. | {"Dana R.": "wrk_3b90"} |
decisions | object, in the JSON body | No | Your answers where the two files disagree, from Preview an import's decisions: the decision key to the side chosen, jobs (the jobs file's value) or money (the money file's). | {"W-1001:status": "money"} |
Try it with your key
Paste your key and change the values. The box builds the call as a cURL line and a fetch line, ready to copy. It never sends anything itself.
Your key stays in this page and is never sent anywhere. Copy the line below and run it yourself.
What comes back
accepted and position, rehearsal true, then the same report Commit an import gives: imported, skipped and refused per row, counts, gaps, finance and payments counts, and figures, the totals the files themselves state.
It never deletes anything. It changes only what the command names, and it writes the change to the job's history with who asked for it.
Every field in the answer
Types are read from the example answer. Money is a plain number in the company's currency. A time carries its offset from UTC (Z is UTC). Ids are opaque text. A field with no line of its own here has its name spelled out; the common fields mean the same on every page.
| Field | Type | Meaning |
|---|---|---|
accepted | true or false | True when the command ran. A command that cannot run is an error instead. |
position | whole number | Where the change landed in the event log. Pass it as after on a read to see your own write. |
rehearsal | true or false | The rehearsal. |
imported | list of objects | The imported. |
imported[].line | whole number | The line. |
imported[].ticket | text | The job number the ticket shows. |
imported[].number | whole number | The number people say out loud, such as the job number. |
imported[].gaps | list | The gaps. |
skipped | list | The skipped. |
refused | list of objects | The refused. |
refused[].line | whole number | The line. |
refused[].ticket | text | The job number the ticket shows. |
refused[].reasons | list of text | The reasons. |
counts | object | The counts. |
counts.imported | whole number | The imported. |
counts.skipped | whole number | The skipped. |
counts.refused | whole number | The refused. |
counts.incomplete | whole number | The incomplete. |
examples | whole number | The examples. |
finance | object | The finance. |
finance.imported | list | The imported. |
finance.skipped | list | The skipped. |
finance.refused | list | The refused. |
finance.counts | object | The counts. |
finance.counts.imported | whole number | The imported. |
finance.counts.skipped | whole number | The skipped. |
finance.counts.refused | whole number | The refused. |
payments | object | The payments. |
payments.imported | list | The imported. |
payments.skipped | list | The skipped. |
payments.refused | list | The refused. |
payments.counts | object | The counts. |
payments.counts.imported | whole number | The imported. |
payments.counts.skipped | whole number | The skipped. |
payments.counts.refused | whole number | The refused. |
payments.counts.amount | money (decimal as text) | The amount. In the company's currency. |
figures | object | The figures. |
figures.money | value or null | The money. |
figures.payments | value or null | The payments. |
figures.span | value or null | The span. |
Why it exists
A preview adds up the rows. A rehearsal runs the real commands, so a row that only fails inside a command shows up here and not after the import.
What it leaves out
The app also reads the Finance panel back after a rehearsal. The public API does not: the Finance panel is the app's own screen. Compare figures with Job money after a real import instead.
Safe to repeat
Nothing is kept, so run it as often as you like. Needs read access to Jobs, as in the app.
Errors that apply
| Code | Status | What it means |
|---|---|---|
| `missing_key` | 401 | Send your key as Authorization: Bearer hh_live_... |
| `unknown_key` | 401 | That key is not one we issued, or it was revoked. |
| `no_access` | 403 | This credential does not reach that. Ask the person who made it for access. |
| `not_found` | 404 | No such record in the companies this credential reaches. |
| `out_of_scope` | 404 | No such company in the companies this credential reaches. |
| `invalid` | 422 | Some fields were refused. See fields. |
| `missing_idempotency_key` | 400 | Send an Idempotency-Key header on every command. |
| `idempotency_mismatch` | 409 | This Idempotency-Key was used with a different body. |
| `idempotency_in_progress` | 409 | A command with this Idempotency-Key is still running. Wait a moment and send it again. |
| `no_credits` | 402 | Out of credits. Top up on Settings › Credits, or turn on auto top-up. |
Related
- List import systems: The systems a book can be imported from, and for each the steps to get its file out, what the file cannot carry, and which one this workspace used last.
- Get import fields: Every field an import reads, for the jobs file and the money file: its label, its tier and what leaving it blank costs.
- Get import template: A CSV to fill in, with every column the import reads and three example rows, for the jobs file, the money file or a payments list.
- Stage import: Send one export file (CSV or Excel) and get back what each column looks like and the mapping we propose. Nothing is imported yet.
- List import statuses: The status words the staged files use, how many rows carry each, and which of our statuses each should land on. Nothing is written.
- List import job types: The job-type words the staged files use, how many rows carry each, and which of our job types each should land on. Nothing is written.
- Preview import: Read the staged files against this workspace and say what an import would do, row by row: what lands, what is already here, what is refused and why.
- Commit import: Import every clean row of the staged files: the jobs, then the money on them. Rows already here are skipped, so sending it twice adds nothing.
- The same records in the app: the Jobs panel.
- How the API fits together: the model, API keys, errors and the MCP server.