Import an Executed Contract into SpotDraft
Goal
Ingest a contract that was executed outside SpotDraft so it still becomes part of your SpotDraft repository and can be found later by your own system identifiers.
When to use this
Use this when the contract was signed outside SpotDraft but still needs to appear in the SpotDraft repository for search, reporting, and downstream linkage.
Endpoints used
POST /api/v2.1/public/contracts/executed_contracts/POST /api/v2.1/public/contracts/{contract_id}/external_metadataGET /api/v2.1/public/contracts/by_external_metadata/{external_metadata_id}
Prerequisites
- a valid public API key
- the final executed file available as base64
- the right
contract_type_idfor the repository record you want to create - the upstream system id you want to keep attached to this contract
Overview
This flow is workspace-specific at two points:
- the executed-contract
contract_type_idmust be accessible in the target workspace - the uploaded file must be a valid PDF payload, not just any base64 string
1. Create the executed contract record
- Python
- Node.js
- curl
import requests
base_url = "https://api.in.spotdraft.com" # Replace with your workspace region.
headers = {
"client-id": SPOTDRAFT_CLIENT_ID,
"client-secret": SPOTDRAFT_CLIENT_SECRET,
"Content-Type": "application/json",
}
contract = requests.post(
f"{base_url}/api/v2.1/public/contracts/executed_contracts/",
headers=headers,
json={
"contract_name": "Acme Executed MSA",
"contract_type_id": EXECUTED_CONTRACT_TYPE_ID,
"file_name": "executed-msa.pdf",
"file_base64": PDF_FILE_BASE64,
"creator_organization_entity_id": CREATOR_ORGANIZATION_ENTITY_ID,
"counterparty_organization_name": "Acme Corporation",
"counterparty_is_individual": False,
"counterparty_poc_details": {
"first_name": "Avery",
"last_name": "Stone",
"email": "legal@acme.example",
},
"external_metadata": {
"id": "docusign-envelope-77891",
"integration_name": "DocuSign",
"record_type": "Envelope",
},
},
timeout=30,
).json()
const baseUrl = 'https://api.in.spotdraft.com'; // Replace with your workspace region.
const headers = {
'client-id': process.env.SPOTDRAFT_CLIENT_ID,
'client-secret': process.env.SPOTDRAFT_CLIENT_SECRET,
'Content-Type': 'application/json',
};
const response = await fetch(`${baseUrl}/api/v2.1/public/contracts/executed_contracts/`, {
method: 'POST',
headers,
body: JSON.stringify({
contract_name: 'Acme Executed MSA',
contract_type_id: Number(process.env.SPOTDRAFT_EXECUTED_CONTRACT_TYPE_ID),
file_name: 'executed-msa.pdf',
file_base64: process.env.PDF_FILE_BASE64,
creator_organization_entity_id: Number(process.env.SPOTDRAFT_CREATOR_ENTITY_ID),
counterparty_organization_name: 'Acme Corporation',
counterparty_is_individual: false,
counterparty_poc_details: {
first_name: 'Avery',
last_name: 'Stone',
email: 'legal@acme.example',
},
external_metadata: {
id: 'docusign-envelope-77891',
integration_name: 'DocuSign',
record_type: 'Envelope',
},
}),
});
const contract = await response.json();
curl --request POST \
--url https://api.in.spotdraft.com/api/v2.1/public/contracts/executed_contracts/ \
--header "client-id: $SPOTDRAFT_CLIENT_ID" \
--header "client-secret: $SPOTDRAFT_CLIENT_SECRET" \
--header "Content-Type: application/json" \
--data '{
"contract_name": "Acme Executed MSA",
"contract_type_id": '"$SPOTDRAFT_EXECUTED_CONTRACT_TYPE_ID"',
"file_name": "executed-msa.pdf",
"file_base64": "'"$PDF_FILE_BASE64"'",
"creator_organization_entity_id": '"$SPOTDRAFT_CREATOR_ENTITY_ID"',
"counterparty_organization_name": "Acme Corporation",
"counterparty_is_individual": false,
"counterparty_poc_details": {
"first_name": "Avery",
"last_name": "Stone",
"email": "legal@acme.example"
},
"external_metadata": {
"id": "docusign-envelope-77891",
"integration_name": "DocuSign",
"record_type": "Envelope"
}
}'
2. Upsert richer external metadata if needed
If the first import payload only carried the minimum identifier, you can enrich it after the record is created.
- Python
- Node.js
- curl
requests.post(
f"{base_url}/api/v2.1/public/contracts/{HISTORICAL_CONTRACT_ID}/external_metadata",
headers=headers,
json={
"external_metadata": {
"id": "docusign-envelope-77891",
"integration_name": "DocuSign",
"record_type": "Envelope",
"record_data": {
"executed_at": "2026-04-19T14:25:00Z",
"owner_email": "owner@acme.example",
},
}
},
timeout=30,
).raise_for_status()
await fetch(`${baseUrl}/api/v2.1/public/contracts/${process.env.SPOTDRAFT_HISTORICAL_CONTRACT_ID}/external_metadata`, {
method: 'POST',
headers,
body: JSON.stringify({
external_metadata: {
id: 'docusign-envelope-77891',
integration_name: 'DocuSign',
record_type: 'Envelope',
record_data: {
executed_at: '2026-04-19T14:25:00Z',
owner_email: 'owner@acme.example',
},
},
}),
});
curl --request POST \
--url "https://api.in.spotdraft.com/api/v2.1/public/contracts/$SPOTDRAFT_HISTORICAL_CONTRACT_ID/external_metadata" \
--header "client-id: $SPOTDRAFT_CLIENT_ID" \
--header "client-secret: $SPOTDRAFT_CLIENT_SECRET" \
--header "Content-Type: application/json" \
--data '{
"external_metadata": {
"id": "docusign-envelope-77891",
"integration_name": "DocuSign",
"record_type": "Envelope",
"record_data": {
"executed_at": "2026-04-19T14:25:00Z",
"owner_email": "owner@acme.example"
}
}
}'
3. Verify the imported contract is discoverable
- Python
- Node.js
- curl
contracts = requests.get(
f"{base_url}/api/v2.1/public/contracts/by_external_metadata/docusign-envelope-77891",
headers=headers,
timeout=30,
).json()
const contractsResponse = await fetch(
`${baseUrl}/api/v2.1/public/contracts/by_external_metadata/docusign-envelope-77891`,
{headers},
);
const contracts = await contractsResponse.json();
curl --request GET \
--url https://api.in.spotdraft.com/api/v2.1/public/contracts/by_external_metadata/docusign-envelope-77891 \
--header "client-id: $SPOTDRAFT_CLIENT_ID" \
--header "client-secret: $SPOTDRAFT_CLIENT_SECRET"
Production checklist
- the SpotDraft historical contract id, such as
H-204 - the source execution system id in
external_metadata.id - the original execution timestamp in your own metadata model if downstream reporting depends on it
Production notes
- The API validates the uploaded PDF content.
- Persist the historical contract id returned from the create step before trying to enrich metadata later.
Common failure points
-
inaccessible executed-contract type A contract type id from another workspace or environment will fail even if the request shape is valid.
-
invalid uploaded file The import call expects a real PDF payload.