
How to Bulk Import Legacy Contracts Into a CLM With an API
Why bulk imports go wrong
Most companies buying a contract management system already have years of contracts somewhere else: a shared drive, SharePoint folders, email attachments, an old document management system, and a spreadsheet that was meant to track all of it and stopped being updated in 2023.
Getting those contracts into the new system is where many CLM projects stall. Not because uploading files is hard, but because a bulk import surfaces every question nobody answered: which version is the signed one, which contracts still matter, who owns them, and what happens when the upload fails at file 3,412.
This guide covers the API route, which is the right one once you are past a few hundred files or want metadata to arrive with each contract. If your contracts are mostly tracked in a spreadsheet today, read our Excel to CLM migration guide first; this one picks up where the files themselves need to move.
- Best for
- Hundreds to tens of thousands of files, or imports that must carry metadata
- Who runs it
- A developer, an integration partner, or an AI agent with a scoped key
- The hard part
- The inventory and the mapping, not the upload
- Must have
- Your own reference ID per contract, so retries never duplicate
- Run first
- A pilot with one folder
Step 1: Build the inventory
Before any upload, list what you have. A good inventory is a spreadsheet or CSV with one row per contract and at least these columns:
Then decide what to bring across. A workable rule for most in-house teams:
- Migrate: contracts in force, anything that auto-renews, contracts with surviving obligations (confidentiality, indemnities, data protection), and anything you must retain.
- Archive: expired agreements with nothing surviving, drafts that were never signed, and duplicates.
Agree the rule with legal and finance up front. Changing it halfway through means re-running the inventory.
Step 2: Map old structure to new
Your old folders rarely match the new system one to one. Decide, folder by folder, where each group goes, and which spreadsheet columns map to which fields.
Keep two kinds of fields apart:
- Fields you already know from your old system or spreadsheet, such as the CRM opportunity ID or the internal owner. Set these during the import.
- Fields the CLM can read from the contract, such as end date or governing law. Many CLMs extract these with AI after import, so you do not need to type them, but check when that extraction runs before you plan reports around it.
Step 3: Make the import safe to re-run
Every large import fails somewhere: a corrupt PDF, a file over the size limit, a network timeout, a rate limit. Design for it from the start.
- Give every row a stable reference
- Create the document with that reference
- Upload the file
- Wait until it is processed
- Set the known fields
- Log the result per row
Stable references are the most important design choice. If the API lets you attach your own reference to each document and refuses a second document with the same reference, you can simply re-run the whole import after a failure: completed rows are skipped, failed ones are retried.
Logging per row turns a failed run into a to-do list. Record the reference, the new document ID, the status and any error. At the end, the log is also your proof that every contract in the inventory made it across.
Respect the limits. Check the API's file types, maximum file size and rate limits, and slow the script down rather than hammering the API. Convert unsupported formats, such as old .doc files or scanned TIFFs, before the run.
Step 4: Pilot, check, then run everything
Run one folder first, ideally a messy one. Then check, by hand, a sample of the imported contracts:
| Check | Why |
|---|---|
| File opens and is the signed version | Inventories often point at drafts |
| It landed in the right space or folder | Mapping errors show up here first |
| Known fields are correct | Column mapping mistakes are silent |
| Extracted fields look plausible | Catches scanned or image-only files |
| The row count matches the inventory | Nothing was skipped quietly |
Fix the script, re-run (safely, thanks to the references), then run the rest in batches. Keep the old source read only until the final count matches, then archive it.
How to do this in Bind
The Bind API, a REST API with public documentation, is included in every plan at no extra cost and is designed for exactly this kind of import. The documentation, a complete upload-and-sync script in TypeScript, and the OpenAPI specification are public at help.bindlegal.com/developers.
Here is one contract going through the import from Bind's side: created in the space, its known field set from the source system, and a request for a space the import was never given refused.
To run a bulk import into Bind:
- Create an API client for the import. In Organization settings → API access → New API client, name it "Legacy import", grant Read and write to the destination spaces only, and create a key with a 30 or 90 day expiry, since the import is temporary.
- Read the fields of each space. Call
GET /v1/spaces/{id}/fieldsto get the field IDs and types, and map your inventory columns to the manual fields you want to set. - Create each document with your reference.
POST /v1/documentswith the space, file name, content type, size, title andexternal_referenceset to the source path or old system ID. Bind returns an upload URL. A second document with the same reference is refused, so re-runs are safe. - Upload and wait. Upload the file to the returned URL, then poll the document until its
processing_statusisready(orfailed, which you log and retry). Bind accepts PDF, Word, Excel and PowerPoint files up to 100 MB. - Set the known fields.
PATCHthe document's title and manual fields, sending itsetagasIf-Matchso the import never overwrites a change someone has already made in Bind. - Let AI autofill do the rest. Fields set to AI autofill, such as end date or counterparty, are filled by Bind from the contract itself, so your inventory only needs the facts the contracts do not contain. They are not filled at the moment of upload, so check them after the import rather than in the script.
When the import is done, revoke the key. Your contracts are then in spaces your team can search, ask questions of in the Bind chat, and set reminders on.
For the bigger picture, Aku Pöllänen, Bind's CEO, explains how Bind handles contracts from draft to signature:
Bind itself is ISO 27001 certified, SOC 2 Type I compliant, and GDPR compliant. It is used by in-house legal teams at companies including Atria, listed on Nasdaq Helsinki, and Outdoor Holding, listed on Nasdaq in the US.
Ready to simplify your contracts?
See how Bind helps teams manage contracts from draft to signature in one platform.
Frequently asked questions
- How do you bulk upload contracts to a CLM?
- Most CLMs offer two routes: a drag-and-drop upload in the interface, which works for hundreds of files, and an API, which works for thousands and can carry metadata with each file. An API import runs as a script or agent that reads your inventory, creates each document in the right folder with your own reference ID, uploads the file, waits for processing, and sets the fields you already know, such as counterparty or deal ID.
- How long does a contract migration take?
- The upload itself is usually the quick part. Most of the time goes into the inventory (finding every contract and its latest signed version), deciding what to bring across, mapping your old folders and spreadsheet columns to the new system, and checking the result. Run a pilot with one folder first; it tells you more about the real timeline than any estimate.
- Should you migrate every old contract?
- Usually not. Bring across contracts that are still in force, those that auto-renew, those with surviving obligations such as confidentiality or indemnities, and anything you are legally required to retain. Expired agreements with no surviving terms can often stay in an archive. Agree the rule with legal and finance before you start, not halfway through.
- How do you avoid duplicate contracts when importing?
- Give every contract a stable reference before you import it, such as the original file path or the record ID in your old system, and use an import method that refuses a second document with the same reference. Then a script that crashes and restarts, or a batch that runs twice, cannot create duplicates. In the Bind API this is the external_reference field, which is unique among each API client’s documents.
- Does Bind charge for API imports?
- No. The Bind API is included in every plan, Starter, Business and Enterprise, at no extra cost.
Bind is trusted by legal teams across Europe and the US

