Quickstart
The first calls to the planned CoreLink API, identifying your key, reading invoices page by page and issuing an invoice safely.
Design preview: these calls don't work yet
The CoreLink API is being designed. This guide shows how an integration will work so the design can be reviewed; no server answers these requests yet.
Before you start
- A test API key (
clk_test_…) from a sandbox company. Keys will be created in CoreLink by a company administrator. See Authentication. - A server-side environment. Keys are secrets: never call the API from a browser or a mobile app.
1. Identify your key
GET /v1/me returns the company the key belongs to, its environment and its scopes. Call it first to confirm you are pointing at the company and environment you expect.
curl https://corelink.piensait.com/api/v1/me \
-H "Authorization: Bearer $CORELINK_API_KEY"const response = await fetch("https://corelink.piensait.com/api/v1/me", {
headers: { Authorization: `Bearer ${process.env.CORELINK_API_KEY}` },
});
const me = await response.json();
console.log(me.company.name, me.environment, me.scopes);{
"key": {
"id": "key_2Wm7Rt",
"prefix": "clk_test_4f9a",
"name": "ERP sync — staging",
"created_at": "2026-09-01T12:00:00Z"
},
"company": {
"id": "cmp_0c1d2e3f",
"name": "Ferretería Horizonte S.A.S.",
"trade_name": "Horizonte",
"tax_id": "900555123",
"check_digit": "4"
},
"environment": "test",
"scopes": [
"parties:read",
"products:read",
"invoices:read",
"invoices:write"
]
}2. Read invoices page by page
Lists return { "data": [...], "next_cursor": "..." }. Follow next_cursor until it is null. To synchronize, keep the time of your last run and pass it as updated_since.
curl "https://corelink.piensait.com/api/v1/invoices?status=validated&updated_since=2026-09-01T00:00:00Z&limit=50" \
-H "Authorization: Bearer $CORELINK_API_KEY"// Reads every page: follow next_cursor until it is null.
let cursor: string | null = null;
do {
const url = new URL("https://corelink.piensait.com/api/v1/invoices");
url.searchParams.set("updated_since", lastSync.toISOString());
url.searchParams.set("limit", "100");
if (cursor) url.searchParams.set("cursor", cursor);
const response = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.CORELINK_API_KEY}` },
});
const page = await response.json();
for (const invoice of page.data) save(invoice);
cursor = page.next_cursor;
} while (cursor);Each invoice carries its status before the tax authority:
| Status | Meaning |
|---|---|
issued |
Finalized and ready to transmit. |
transmitting |
Sent to the tax authority; waiting for its answer. |
validated |
Validated; it has its CUFE and final number. |
rejected |
Rejected by the tax authority; see tax_authority_messages. |
The full list of statuses is in the API reference. Validated invoices can be downloaded with GET /v1/invoices/{id}/pdf and GET /v1/invoices/{id}/xml.
3. Issue an invoice
POST /v1/invoices/{id}/issue transmits an invoice that is already finalized in CoreLink. It answers 202 Accepted: the tax authority answers later, so read the invoice again to see the final status.
curl -X POST https://corelink.piensait.com/api/v1/invoices/inv_5KfT0a/issue \
-H "Authorization: Bearer $CORELINK_API_KEY" \
-H "Idempotency-Key: 8b0e5c1a-3f2d-4e6b-9a7c-1d2e3f4a5b6c"// Keep the key with the operation: reuse it only to retry this same call.
const idempotencyKey = crypto.randomUUID();
const response = await fetch("https://corelink.piensait.com/api/v1/invoices/inv_5KfT0a/issue", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CORELINK_API_KEY}`,
"Idempotency-Key": idempotencyKey,
},
});{
"invoice_id": "inv_5KfT0a",
"environment": "test",
"status": "transmitting",
"transaction_id": "txn_01J9Z7B3K2",
"deduplicated": false,
"correlation_id": "c0f1e2d3-4b5a-4c6d-8e7f-9a0b1c2d3e4f"
}Always send an Idempotency-Key
If the connection drops, retry with the same key: the invoice is transmitted only once. A new operation needs a new key.
Next steps
- Handle errors and retries.
- See every resource in Modules and the API reference.