Skip to main content
POST
/
api
/
v1
/
enterprise
/
eudr
/
batches
Python
import agribackup
from agribackup.rest import ApiException

# Initialize Client
configuration = agribackup.Configuration(host="https://live.agribackup.com/api/v1")
configuration.api_key['ApiKeyAuth'] = 'sk_live_YOUR_API_KEY'

with agribackup.ApiClient(configuration) as api_client:
    try:
        api_instance = agribackup.EnterpriseBatchesApi(api_client)
        response = api_instance.register_batch()
        print(response)
    except ApiException as e:
        print("Exception when calling API: %s\n" % e)
import { AgriBackupClient } from '@agribackup/sdk';

// Initialize Client
const client = new AgriBackupClient({
apiKey: 'sk_live_YOUR_API_KEY',
baseUrl: 'https://live.agribackup.com/api/v1'
});

async function execute() {
try {
const response = await client.batches.registerBatch();
console.log(response);
} catch (error) {
console.error(error);
}
}
import com.agribackup.client.*;
import com.agribackup.client.api.*;
import com.agribackup.client.model.*;

public class Example {
public static void main(String[] args) {
ApiClient defaultClient = Configuration.getDefaultApiClient();
defaultClient.setBasePath("https://live.agribackup.com/api/v1");
defaultClient.setApiKey("sk_live_YOUR_API_KEY");

EnterpriseBatchesApi apiInstance = new EnterpriseBatchesApi(defaultClient);
try {
Object result = apiInstance.registerBatch();
System.out.println(result);
} catch (ApiException e) {
System.err.println("Exception when calling API: " + e.getResponseBody());
}
}
}
using System;
using System.Threading.Tasks;
using AgriBackup.SDK.Api;
using AgriBackup.SDK.Client;
using AgriBackup.SDK.Model;

class Program {
static async Task Main() {
Configuration config = new Configuration();
config.BasePath = "https://live.agribackup.com/api/v1";
config.AddApiKey("ApiKeyAuth", "sk_live_YOUR_API_KEY");

var apiInstance = new EnterpriseBatchesApi(config);
try {
var result = await apiInstance.RegisterBatchAsync();
Console.WriteLine(result);
} catch (ApiException e) {
Console.WriteLine("Exception when calling API: " + e.Message);
}
}
}
curl --request POST \
--url https://live.agribackup.com/api/v1/enterprise/eudr/batches \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'X-API-Key: <api-key>' \
--data '
{
"commodity": "COFFEE",
"countryCode": "KEN",
"hsCode": "090111",
"quantityKg": 5000.5,
"polygonIds": [
"<string>"
],
"vendorIds": [
"<string>"
]
}
'
const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
'X-API-Key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
commodity: 'COFFEE',
countryCode: 'KEN',
hsCode: '090111',
quantityKg: 5000.5,
polygonIds: ['<string>'],
vendorIds: ['<string>']
})
};

fetch('https://live.agribackup.com/api/v1/enterprise/eudr/batches', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://live.agribackup.com/api/v1/enterprise/eudr/batches",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'commodity' => 'COFFEE',
'countryCode' => 'KEN',
'hsCode' => '090111',
'quantityKg' => 5000.5,
'polygonIds' => [
'<string>'
],
'vendorIds' => [
'<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Idempotency-Key: <idempotency-key>",
"X-API-Key: <api-key>"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
"fmt"
"strings"
"net/http"
"io"
)

func main() {

url := "https://live.agribackup.com/api/v1/enterprise/eudr/batches"

payload := strings.NewReader("{\n \"commodity\": \"COFFEE\",\n \"countryCode\": \"KEN\",\n \"hsCode\": \"090111\",\n \"quantityKg\": 5000.5,\n \"polygonIds\": [\n \"<string>\"\n ],\n \"vendorIds\": [\n \"<string>\"\n ]\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
require 'uri'
require 'net/http'

url = URI("https://live.agribackup.com/api/v1/enterprise/eudr/batches")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"commodity\": \"COFFEE\",\n \"countryCode\": \"KEN\",\n \"hsCode\": \"090111\",\n \"quantityKg\": 5000.5,\n \"polygonIds\": [\n \"<string>\"\n ],\n \"vendorIds\": [\n \"<string>\"\n ]\n}"

response = http.request(request)
puts response.read_body
{
  "jobId": "job_998877",
  "status": "PENDING",
  "estimatedDurationSec": 3,
  "createdAt": "2026-06-15T12:00:00Z"
}
{
"code": "VALIDATION_FAILED",
"message": "Invalid polygon coordinates",
"details": [
{
"code": "INVALID_COORDINATE_CLOSURE",
"field": "features[0].properties.area",
"issue": "Area must be specified in hectares and cannot be negative"
}
]
}
{
"code": "VALIDATION_FAILED",
"message": "Invalid polygon coordinates",
"details": [
{
"code": "INVALID_COORDINATE_CLOSURE",
"field": "features[0].properties.area",
"issue": "Area must be specified in hectares and cannot be negative"
}
]
}
{
"code": "VALIDATION_FAILED",
"message": "Invalid polygon coordinates",
"details": [
{
"code": "INVALID_COORDINATE_CLOSURE",
"field": "features[0].properties.area",
"issue": "Area must be specified in hectares and cannot be negative"
}
]
}
{
"code": "VALIDATION_FAILED",
"message": "Invalid polygon coordinates",
"details": [
{
"code": "INVALID_COORDINATE_CLOSURE",
"field": "features[0].properties.area",
"issue": "Area must be specified in hectares and cannot be negative"
}
]
}
{
"code": "VALIDATION_FAILED",
"message": "Invalid polygon coordinates",
"details": [
{
"code": "INVALID_COORDINATE_CLOSURE",
"field": "features[0].properties.area",
"issue": "Area must be specified in hectares and cannot be negative"
}
]
}
{
"code": "VALIDATION_FAILED",
"message": "Invalid polygon coordinates",
"details": [
{
"code": "INVALID_COORDINATE_CLOSURE",
"field": "features[0].properties.area",
"issue": "Area must be specified in hectares and cannot be negative"
}
]
}
Creates a new consolidated EUDR batch and links it to an array of pre-verified polygon IDs. Registering a batch automatically triggers a Copernicus satellite risk assessment across all referenced polygons. Because this process is asynchronous, the endpoint returns 202 Accepted immediately with a jobId. Poll GET /api/v1/enterprise/eudr/jobs/{jobId} or listen for the batch.risk_assessed webhook to retrieve the final consolidatedRiskState.

Request Headers

HeaderRequiredDescription
X-API-KeyYour live API key, e.g. sk_live_....
Idempotency-KeyA UUID v4 string. Replaying the same key within 24 hours returns the original job response without creating a duplicate batch.
X-Sub-Organization-IDOptional subsidiary identifier to scope the batch to a specific business unit.

Request Body

FieldTypeRequiredDescription
commoditystringEUDR commodity type, e.g. COFFEE, COCOA, SOYA.
countryCodestringISO 3-letter country code of origin (e.g. KEN for Kenya, BRA for Brazil).
hsCodestring6-digit Harmonised System (HS) code for the commodity, e.g. 090111.
quantityKgnumberTotal commodity quantity in kilograms.
polygonIdsarray of stringsArray of verified polygon IDs to include in this batch (max 5,000). All polygon IDs must have eudrStatus: COMPLIANT.
vendorIdsarray of stringsOptional list of ERP vendor IDs to link this batch to your Tier-1 supply chain mapping.
{
  "commodity": "COFFEE",
  "countryCode": "KEN",
  "hsCode": "090111",
  "quantityKg": 5000.5,
  "polygonIds": [
    "uuid-polygon-1",
    "uuid-polygon-2"
  ],
  "vendorIds": ["ERP-VEND-991"]
}

Response — 202 Accepted

FieldTypeDescription
jobIdstringUse this ID to poll job status via GET /api/v1/enterprise/eudr/jobs/{jobId}.
statusstringAlways PENDING on acceptance.
estimatedDurationSecintegerEstimated seconds until risk assessment completes.
createdAtstring (ISO-8601)Timestamp when the job was accepted.
The response also includes a Location header pointing to the job status endpoint.
{
  "jobId": "job_998877",
  "status": "PENDING",
  "estimatedDurationSec": 3,
  "createdAt": "2026-06-15T12:00:00Z"
}

Async Completion — batch.risk_assessed Webhook

When the Copernicus risk assessment finishes, AgriBackup fires a batch.risk_assessed event to your registered webhook URL. The event payload is signed with X-AgriBackup-Signature (HMAC-SHA256). Once the batch has a consolidatedRiskState of COMPLIANT, it is ready to be linked to a logistics shipment.

Code Examples

import agribackup
from agribackup.rest import ApiException
import uuid

configuration = agribackup.Configuration(host="https://live.agribackup.com/api/v1")
configuration.api_key['ApiKeyAuth'] = 'sk_live_YOUR_API_KEY'

with agribackup.ApiClient(configuration) as api_client:
    try:
        api_instance = agribackup.EnterpriseBatchesApi(api_client)

        request = agribackup.BatchRegistrationRequest(
            commodity='COFFEE',
            country_code='KEN',
            hs_code='090111',
            quantity_kg=5000.5,
            polygon_ids=['uuid-polygon-1', 'uuid-polygon-2'],
            vendor_ids=['ERP-VEND-991']
        )

        response = api_instance.register_batch(
            idempotency_key=str(uuid.uuid4()),
            batch_registration_request=request
        )
        print("Job accepted:", response.job_id)
    except ApiException as e:
        print("Error:", e)
import { AgriBackupClient } from '@agribackup/sdk';
import { v4 as uuidv4 } from 'uuid';

const client = new AgriBackupClient({
  apiKey: 'sk_live_YOUR_API_KEY',
  baseUrl: 'https://live.agribackup.com/api/v1'
});

async function registerBatch() {
  try {
    const response = await client.batches.registerBatch({
      idempotencyKey: uuidv4(),
      commodity: 'COFFEE',
      countryCode: 'KEN',
      hsCode: '090111',
      quantityKg: 5000.5,
      polygonIds: ['uuid-polygon-1', 'uuid-polygon-2'],
      vendorIds: ['ERP-VEND-991']
    });
    console.log('Job accepted:', response.jobId);
  } catch (error) {
    console.error('Error:', error.message);
  }
}
curl -X POST https://live.agribackup.com/api/v1/enterprise/eudr/batches \
  -H "X-API-Key: sk_live_YOUR_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "commodity": "COFFEE",
    "countryCode": "KEN",
    "hsCode": "090111",
    "quantityKg": 5000.5,
    "polygonIds": ["uuid-polygon-1", "uuid-polygon-2"],
    "vendorIds": ["ERP-VEND-991"]
  }'

Authorizations

X-API-Key
string
header
required

Enterprise API Key provided via the AgriBackup developer console.

Headers

Idempotency-Key
string
required

Unique idempotency key (UUID) to prevent duplicate operations. Safely stored in Redis with a strict 24-hour TTL to prevent memory bloat during saturation attacks.

X-Sub-Organization-ID
string

Optional identifier to partition compliance data (polygons, batches, declarations) for a specific subsidiary or regional business unit within the conglomerate.

Body

application/json

Payload for registering a new consolidated batch

commodity
string
required

EUDR Commodity type or name

Example:

"COFFEE"

countryCode
string
required

ISO 3-letter country code of origin (e.g., KEN for Kenya, BRA for Brazil)

Example:

"KEN"

hsCode
string
required

HS Code (mandatory for dynamic validation)

Example:

"090111"

quantityKg
number
required

Total quantity in kilograms

Example:

5000.5

polygonIds
string[]
required

Array of verified Polygon IDs forming this batch

Maximum array length: 5000

Array of verified Polygon IDs forming this batch

vendorIds
string[]

Optional list of ERP Vendor IDs to explicitly map this batch to the Tier-1 Enterprise Supply Chain

Optional list of ERP Vendor IDs to explicitly map this batch to the Tier-1 Enterprise Supply Chain

Response

Batch registered and risk assessment queued

Response payload for asynchronously accepted jobs

jobId
string
required

The unique asynchronous tracking job ID

Example:

"job_998877"

status
enum<string>
required

Current execution status invariant

Available options:
PENDING
Example:

"PENDING"

estimatedDurationSec
integer<int32>
required

Estimated duration in seconds before consensus or processing lock release

Example:

3

createdAt
string<date-time>
required

Timestamp when the job was accepted

Example:

"2026-06-15T12:00:00Z"