Reference
The API our own app runs on.
REST over JSON. Below is authentication and one worked example of issuing a document - enough to work out how long an integration takes. The full reference, route by route, lives inside the platform once you have signed in.
Authentication
A dispatch system presents its key in x-api-key. The key belongs to
one customer and can only act on that customer: the tenant never travels in the
body or the URL, because the caller writes both.
A person presents a token from their own directory in
Authorization: Bearer. What they may do is decided by the role their
administrator granted, never by a claim in the token.
Security and limits
HTTPS only, with TLS 1.2 or later. Every request first passes a web application firewall with the OWASP rule set and bot protection, which refuses more than 600 requests a minute from one address.
Each key has its own allowance per minute, set by the edition contracted: from 60
to 420 requests. Past it the answer is 429, with
Retry-After and the RateLimit-* headers saying when to
try again.
One key per dispatch system, kept as a secret and revoked from the platform as soon as it is no longer used. It is shown once, and we keep only its hash.
To report a vulnerability, follow our disclosure policy.
Issue a document
The one call that covers 90% of integrations. It returns the identifier, the public URL and the hash of the published PDF.
curl -X POST https://api.deca2u.com/v1/documents \
-H "x-api-key: $DECA2U_KEY" \
-H "Content-Type: application/json" \
-d '{
"siteId": "V204",
"externalRef": "V204-40712",
"data": {
"contractualShipper": {
"name": "Conservas Bahía Norte, S.L.",
"taxId": "B36742180",
"address": "Rúa do Porto 22, 36202 Vigo"
},
"effectiveCarrier": { "name": "Transportes Vega Hermanos, S.L.", "taxId": "B99001122" },
"location": { "origin": "Centro logístico de Vigo", "destination": "Plataforma de Getafe" },
"goods": { "description": "Conserva vegetal en lata", "quantity": 12400, "unit": "kg" },
"transportDate": "2026-07-15",
"vehicle": { "tractorPlate": "1234ABC", "articulated": false }
}
}'
const response = await fetch('https://api.deca2u.com/v1/documents', {
method: 'POST',
headers: {
'x-api-key': process.env.DECA2U_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
siteId: 'V204',
externalRef: 'V204-40712',
data: {
contractualShipper: {
name: 'Conservas Bahía Norte, S.L.',
taxId: 'B36742180',
address: 'Rúa do Porto 22, 36202 Vigo',
},
effectiveCarrier: { name: 'Transportes Vega Hermanos, S.L.', taxId: 'B99001122' },
location: { origin: 'Centro logístico de Vigo', destination: 'Plataforma de Getafe' },
goods: { description: 'Conserva vegetal en lata', quantity: 12400, unit: 'kg' },
transportDate: '2026-07-15',
vehicle: { tractorPlate: '1234ABC', articulated: false },
},
}),
});
if (!response.ok) throw new Error(`DeCA2U answered ${response.status}`);
const { id, url } = await response.json();
import os
import requests
response = requests.post(
"https://api.deca2u.com/v1/documents",
headers={"x-api-key": os.environ["DECA2U_KEY"]},
json={
"siteId": "V204",
"externalRef": "V204-40712",
"data": {
"contractualShipper": {
"name": "Conservas Bahía Norte, S.L.",
"taxId": "B36742180",
"address": "Rúa do Porto 22, 36202 Vigo",
},
"effectiveCarrier": {"name": "Transportes Vega Hermanos, S.L.", "taxId": "B99001122"},
"location": {"origin": "Centro logístico de Vigo", "destination": "Plataforma de Getafe"},
"goods": {"description": "Conserva vegetal en lata", "quantity": 12400, "unit": "kg"},
"transportDate": "2026-07-15",
"vehicle": {"tractorPlate": "1234ABC", "articulated": False},
},
},
timeout=10,
)
response.raise_for_status()
issued = response.json()
using System.Net.Http.Json;
var http = new HttpClient { BaseAddress = new Uri("https://api.deca2u.com/") };
http.DefaultRequestHeaders.Add("x-api-key", Environment.GetEnvironmentVariable("DECA2U_KEY"));
var response = await http.PostAsJsonAsync("v1/documents", new
{
siteId = "V204",
externalRef = "V204-40712",
data = new
{
contractualShipper = new
{
name = "Conservas Bahía Norte, S.L.",
taxId = "B36742180",
address = "Rúa do Porto 22, 36202 Vigo",
},
effectiveCarrier = new { name = "Transportes Vega Hermanos, S.L.", taxId = "B99001122" },
location = new { origin = "Centro logístico de Vigo", destination = "Plataforma de Getafe" },
goods = new { description = "Conserva vegetal en lata", quantity = 12400, unit = "kg" },
transportDate = "2026-07-15",
vehicle = new { tractorPlate = "1234ABC", articulated = false },
},
});
response.EnsureSuccessStatusCode();
var issued = await response.Content.ReadFromJsonAsync<Issued>();
var body = """
{
"siteId": "V204",
"externalRef": "V204-40712",
"data": {
"contractualShipper": {
"name": "Conservas Bahía Norte, S.L.",
"taxId": "B36742180",
"address": "Rúa do Porto 22, 36202 Vigo"
},
"effectiveCarrier": { "name": "Transportes Vega Hermanos, S.L.", "taxId": "B99001122" },
"location": { "origin": "Centro logístico de Vigo", "destination": "Plataforma de Getafe" },
"goods": { "description": "Conserva vegetal en lata", "quantity": 12400, "unit": "kg" },
"transportDate": "2026-07-15",
"vehicle": { "tractorPlate": "1234ABC", "articulated": false }
}
}
""";
var request = HttpRequest.newBuilder(URI.create("https://api.deca2u.com/v1/documents"))
.header("x-api-key", System.getenv("DECA2U_KEY"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
var response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
<?php
$payload = [
'siteId' => 'V204',
'externalRef' => 'V204-40712',
'data' => [
'contractualShipper' => [
'name' => 'Conservas Bahía Norte, S.L.',
'taxId' => 'B36742180',
'address' => 'Rúa do Porto 22, 36202 Vigo',
],
'effectiveCarrier' => ['name' => 'Transportes Vega Hermanos, S.L.', 'taxId' => 'B99001122'],
'location' => ['origin' => 'Centro logístico de Vigo', 'destination' => 'Plataforma de Getafe'],
'goods' => ['description' => 'Conserva vegetal en lata', 'quantity' => 12400, 'unit' => 'kg'],
'transportDate' => '2026-07-15',
'vehicle' => ['tractorPlate' => '1234ABC', 'articulated' => false],
],
];
$curl = curl_init('https://api.deca2u.com/v1/documents');
curl_setopt_array($curl, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['x-api-key: ' . getenv('DECA2U_KEY'), 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
]);
$issued = json_decode(curl_exec($curl), true);
201 response:
{
"id": "8h86UiouAH2eZwOrS4di1Q",
"url": "https://doc.deca2u.com/yQRjIVKxGsA4SqJoZDn_hw/8h86UiouAH2eZwOrS4di1Q.pdf",
"publishedAt": "2026-07-15T06:31:02.144Z",
"publicUntil": "2026-07-22T23:59:59.000Z",
"pdfHash": "9f2c…",
"qr": "<svg xmlns=…>", // only with ?qr=1
"externalRef": "V204-40712"
}
If the consignment already had a document it answers 200 with
alreadyIssuedAs and the existing URL, rather than issuing a second
one. If a required letter is missing it answers 422 and lists which:
an incomplete document is not a DeCA, and it is not published.
The rest - correcting, reissuing, the customer's own catalogues, identifier blocks for a site with no line - is documented route by route inside the platform, under Administration, for whoever already has an account.