Exporting your Coordinate data
coordinate_export.py (scroll to bottom for download link) downloads everything your account exposes
through the
Coordinate API into a folder of JSON files on your own machine — one file
per project,
with attachments included.
Quick start
1. Get an API key
- Sign in to Coordinate as an admin.
- Go to Settings → API and Integrations.
- Under Your API Keys, click Add API Key, enter a nickname, and confirm.
-
Click Reveal key next to the new key and copy it.
It looks like
secret_xxxxxxxxxxxxxxxx.
2. Download the exporter
Save coordinate_export.py to a folder you can find again,
for example your Downloads folder.
3. Run it Windows
- Install Python from python.org/downloads. On the first installer screen, tick Add python.exe to PATH, then click Install Now.
-
Open PowerShell (Start menu → type
powershell). - Move to the folder holding the script and run it:
cd $HOME\Downloads
python coordinate_export.py --api-key secret_xxxxxxxx --vendor-name "Acme Inc" --out .\my-export
4. Run it Mac
-
Python 3 is already installed. Confirm with
python3 --version(3.8 or newer). -
Open Terminal (Command-Space, type
terminal). - Move to the folder holding the script and run it:
cd ~/Downloads
python3 coordinate_export.py --api-key secret_xxxxxxxx --vendor-name "Acme Inc" --out ./my-export
That's it
-
Replace
secret_xxxxxxxxwith your key andAcme Incwith your company name. -
Nothing to install beyond Python — no
pip install, no virtualenv. - A large account can take hours. If it stops for any reason, run the exact same command again — it resumes and never re-downloads what it already has.
-
When it finishes, open
export_status.jsonin the output folder and check thestatusfield.
What you need
-
Python 3.8 or newer. Nothing else. No
pip install, no virtualenv.-
macOS and most Linux systems already have it: run
python3 --version. -
Windows: install from
python.org, then
use
pythoninstead ofpython3in the commands below.
-
macOS and most Linux systems already have it: run
-
An API key. In Coordinate, go to
Settings → API and Integrations
and create one under Your API Keys. You need to be an
admin. The key looks like
secret_xxxxxxxxxxxxxxxx.
Running it
python3 coordinate_export.py --api-key secret_xxxxxxxx --vendor-name "Acme Inc" --out ./my-export
You will see progress as it works:
Coordinate export - contacting https://app.coordinatehq.com
Exporting Acme Inc (3f2a1b9c) - 143 of 143 project(s)
[ok] Acme Onboarding - 41 tasks, 3 subtasks, 212 comments, 9/9 files (12.1 MB) in 4.1s
...
EXPORT COMPLETE
projects 143 completed, 0 failed, 0 not yet exported
tasks 5,120 subtasks 288 comments 18,022
files 903 downloaded, 0 failed, 7.6 GB
elapsed 01:12:44
output /Users/you/my-export/Acme_Inc
A large account can take a while. If it stops for any reason — you close the laptop, the network drops, you press Ctrl-C — just run the exact same command again. It picks up where it left off and does not re-download anything it already has.
--vendor-name is only used to name the output folder. The API
does not report your
company name, so if you leave it off you will be asked for it, and the folder
falls back to your
account id.
What you get
my-export/
Acme Inc/
export_status.json <- start here
account.json
organizations.json
projects/
0001__Acme_Onboarding__3f2a1b9c.json
0002__...
files/ <- attachments larger than 10 MB
export.log
Check export_status.json first. Its
status field tells you
whether the export actually finished:
status
|
Meaning |
|---|---|
completed
|
Everything exported successfully. |
completed_with_errors
|
Finished, but something failed — see the errors
list. Re-run to retry.
|
interrupted
|
Stopped part way. Re-run the same command to continue. |
in_progress
|
Still running, or killed before it could finish. Re-run. |
failed
|
Could not start — usually a bad API key or unreachable site. |
It also contains a known_gaps list describing the handful of
things the API cannot
return, so you know exactly what is and is not in your export.
Inside a project file
Each project is one JSON document:
-
project— name, description, status, manager, tags, custom field values, attachments -
groups— each with itstasksnested inside;group_internalmarks team-only groups -
tasks_ungrouped— tasks not in any group -
inside each task:
task_checklists(with any assigned subtask nested under its item),time_tracking,form_data,task_assignments,files, and its owndiscussion -
goals,progress_reports,collaborators,pages,organizations -
discussion— the project-level comment thread; each comment hasprivate: true/false -
warnings— things worth knowing but not failures (an empty group whose internal flag could not be determined, a checklist item pointing at a deleted subtask) -
errorsandpartial— see below
When something goes wrong
The exporter is built to keep going and tell you exactly what it could not get, rather than stopping at the first problem.
-
One bad project does not stop the run. It is marked
failedinexport_status.jsonwith the reason, and the remaining projects continue. Re-running retries it. -
One bad section does not lose the project. If, say,
the progress-reports
endpoint fails while tasks and comments succeed, you still get a project
file containing
everything that worked. It is marked
"partial": true, and itserrorsarray says what is missing. -
One bad attachment does not lose the file's record.
The entry stays in the JSON
with a
download_errorexplaining what happened, so you know a file existed and can chase it. -
Nothing is dropped silently. If the server returns records
the exporter cannot
make sense of, it counts them and records that in
errors.
So after a run, check in this order:
-
export_status.json→status— did the run finish? -
export_status.json→errors— the full list of problems across the whole export. -
Any project file with
"partial": true— itserrorsarray explains what that project is missing. -
export.log— the full technical detail, including tracebacks if anything unexpected happened.
Re-running the same command retries everything that failed and leaves everything that succeeded alone.
Attachments
Files under 10 MB are embedded directly in the JSON as base64 in
content_base64. Larger
ones are written into the files/ folder and the JSON records
a content_path
pointing at them. Every file also has a sha256 so you can verify
it.
To pull one back out of a JSON file:
import base64, json
doc = json.load(open("projects/0001__Acme_Onboarding__3f2a1b9c.json"))
for f in doc["project"]["files"]:
if f["content_base64"]:
open(f["file_name"], "wb").write(base64.b64decode(f["content_base64"]))
Change the threshold with --inline-max-bytes, or skip file contents
entirely with
--skip-files if you only want the text and structure.
Other options
| Option | What it does |
|---|---|
--base-url
|
Point at a different site address if you use a custom domain. |
--only-project ID
|
Export a single project. Repeat for more than one. |
--force
|
Re-export projects that already completed. |
--skip-files
|
Record attachment details but do not download them. |
--quiet / --verbose
|
Less or more output. |
--timeout
|
Seconds to wait per request (default 120). |
You can also set the key as an environment variable instead of passing
--api-key:
export COORDINATE_API_KEY=secret_xxxxxxxx
python3 coordinate_export.py --out ./my-export
On Windows PowerShell the equivalent is:
$env:COORDINATE_API_KEY = "secret_xxxxxxxx"
python coordinate_export.py --out .\my-export
Run python3 coordinate_export.py --help for the full list.
Exit codes
For anyone scripting around it: 0 completed, 1
finished with errors,
2 interrupted, 3 could not start.