Skip to main content
Once your farm-boundary polygons pass satellite screening and carry a COMPLIANT status, you consolidate them into a batch that represents a single shipment unit of a regulated commodity. A batch ties together the commodity, origin country, HS code, quantity, and the verified polygon IDs that prove the land was not deforested. Registering a batch triggers an automated Copernicus risk assessment and anchors the result on the Hedera ledger. Like polygon ingestion, the endpoint returns 202 Accepted immediately and completes asynchronously.
Every batch requires at least one polygon ID with eudrStatus: COMPLIANT. If any polygon you include is still PENDING or is HIGH_RISK, the API returns a 400 Bad Request. Complete polygon ingestion first — see Polygon Ingestion.

Prerequisites

  • One or more polygon IDs with eudrStatus: COMPLIANT.
  • The commodity’s HS code (6-digit minimum) and ISO 3-letter country-of-origin code.
  • A batch.risk_assessed webhook subscription to receive the completion event (see Webhooks Setup).

Step-by-step batch registration

1

Submit the batch registration request

Send a POST to /api/v1/enterprise/eudr/batches. Supply a UUID Idempotency-Key header to ensure the request is safe to retry.Required fields:
FieldTypeDescription
commoditystringEUDR commodity name, e.g. "COFFEE"
countryCodestringISO 3-letter origin code, e.g. "KEN"
hsCodestringHS code for dynamic validation, e.g. "090111"
quantityKgnumberTotal quantity in kilograms
polygonIdsstring[]Array of COMPLIANT polygon IDs (max 5,000)
Optional field:
FieldTypeDescription
vendorIdsstring[]ERP vendor IDs to map this batch to your Tier-1 supply chain
import agribackup
from agribackup.rest import ApiException
import uuid

configuration = agribackup.Configuration()
configuration.api_key['ApiKeyAuth'] = 'sk_live_YOUR_API_KEY'

with agribackup.ApiClient(configuration) as api_client:
    try:
        batches_api = agribackup.EnterpriseBatchesApi(api_client)
        job = batches_api.register_batch(
            idempotency_key=str(uuid.uuid4()),
            batch_registration_request={
                "commodity": "COFFEE",
                "countryCode": "KEN",
                "hsCode": "090111",
                "quantityKg": 5000.5,
                "polygonIds": ["poly_abc123", "poly_def456"],
                "vendorIds": ["ERP-VEND-991"]
            }
        )
        print("Job accepted:", job.job_id)
        print("Estimated duration (s):", job.estimated_duration_sec)
    except ApiException as e:
        print("Error:", e)
import { AgriBackupClient } from '@agribackup/sdk';
import { randomUUID } from 'crypto';

const client = new AgriBackupClient({ apiKey: 'sk_live_YOUR_API_KEY' });

async function registerBatch() {
  try {
    const job = await client.batches.register(
      {
        commodity: 'COFFEE',
        countryCode: 'KEN',
        hsCode: '090111',
        quantityKg: 5000.5,
        polygonIds: ['poly_abc123', 'poly_def456'],
        vendorIds: ['ERP-VEND-991']
      },
      { idempotencyKey: randomUUID() }
    );
    console.log('Job accepted:', job.jobId);
    console.log('Estimated duration (s):', job.estimatedDurationSec);
  } catch (error) {
    console.error('Error:', error.message);
  }
}

registerBatch();
curl --request POST \
  --url https://live.agribackup.com/api/v1/enterprise/eudr/batches \
  --header 'X-API-Key: sk_live_YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: 550e8400-e29b-41d4-a716-446655440001' \
  --data '{
    "commodity": "COFFEE",
    "countryCode": "KEN",
    "hsCode": "090111",
    "quantityKg": 5000.5,
    "polygonIds": ["poly_abc123", "poly_def456"],
    "vendorIds": ["ERP-VEND-991"]
  }'
A successful 202 Accepted response:
{
  "jobId": "job_112233",
  "status": "PENDING",
  "estimatedDurationSec": 5,
  "createdAt": "2026-07-08T09:00:00Z"
}
The Location header points to /api/v1/enterprise/eudr/jobs/job_112233 for polling.
2

Retrieve the registered batch

Once the job completes, fetch the batch record with GET /api/v1/enterprise/eudr/batches/{batchId} to confirm its status and linked data.
import agribackup
from agribackup.rest import ApiException

configuration = agribackup.Configuration()
configuration.api_key['ApiKeyAuth'] = 'sk_live_YOUR_API_KEY'

with agribackup.ApiClient(configuration) as api_client:
    try:
        batches_api = agribackup.EnterpriseBatchesApi(api_client)
        batch = batches_api.get_batch(batch_id="uuid-1234")
        print("Batch code:", batch.batch_code)
        print("Status:", batch.status)
        print("Risk state:", batch.consolidated_risk_state)
        print("Linked polygons:", batch.polygon_ids)
    except ApiException as e:
        print("Error:", e)
import { AgriBackupClient } from '@agribackup/sdk';

const client = new AgriBackupClient({ apiKey: 'sk_live_YOUR_API_KEY' });

async function getBatch(batchId) {
  try {
    const batch = await client.batches.get(batchId);
    console.log('Batch code:', batch.batchCode);
    console.log('Status:', batch.status);
    console.log('Risk state:', batch.consolidatedRiskState);
    console.log('Linked polygons:', batch.polygonIds);
  } catch (error) {
    console.error('Error:', error.message);
  }
}

getBatch('uuid-1234');
curl --request GET \
  --url https://live.agribackup.com/api/v1/enterprise/eudr/batches/uuid-1234 \
  --header 'X-API-Key: sk_live_YOUR_API_KEY'
The BatchDetailResponse schema:
{
  "batchId": "uuid-1234",
  "batchCode": "COFFEE-KEN-20260612-ABCDEF",
  "status": "CREATED",
  "consolidatedRiskState": "COMPLIANT",
  "polygonIds": ["poly_abc123", "poly_def456"],
  "shipmentIds": []
}
3

Update a batch before anchoring

You may update a batch’s quantity, commodity description, HS code, or harvest date using PATCH /api/v1/enterprise/eudr/batches/{batchId}, provided it has not yet been anchored on-chain.
import agribackup
from agribackup.rest import ApiException

configuration = agribackup.Configuration()
configuration.api_key['ApiKeyAuth'] = 'sk_live_YOUR_API_KEY'

with agribackup.ApiClient(configuration) as api_client:
    try:
        batches_api = agribackup.EnterpriseBatchesApi(api_client)
        updated = batches_api.update_batch(
            batch_id="uuid-1234",
            batch_update_request={
                "quantity": 4800.0,
                "commodityDescription": "Green Coffee Beans — Washed",
                "hsCode": "090111",
                "harvestDate": "2026-07-15"
            }
        )
        print("Updated batch:", updated)
    except ApiException as e:
        print("Error:", e)
import { AgriBackupClient } from '@agribackup/sdk';

const client = new AgriBackupClient({ apiKey: 'sk_live_YOUR_API_KEY' });

async function updateBatch(batchId) {
  try {
    const updated = await client.batches.update(batchId, {
      quantity: 4800.0,
      commodityDescription: 'Green Coffee Beans — Washed',
      hsCode: '090111',
      harvestDate: '2026-07-15'
    });
    console.log('Updated batch:', updated);
  } catch (error) {
    console.error('Error:', error.message);
  }
}

updateBatch('uuid-1234');
curl --request PATCH \
  --url https://live.agribackup.com/api/v1/enterprise/eudr/batches/uuid-1234 \
  --header 'X-API-Key: sk_live_YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "quantity": 4800.0,
    "commodityDescription": "Green Coffee Beans — Washed",
    "hsCode": "090111",
    "harvestDate": "2026-07-15"
  }'
You cannot update a batch once its consolidatedRiskState has moved past PENDING_RISK_ASSESSMENT and it has been linked to a shipment. Attempting to do so returns 409 Conflict.
4

Delete a batch

To remove a batch that was created in error, send DELETE /api/v1/enterprise/eudr/batches/{batchId}. This permanently removes the record and cannot be undone. Batches that are already linked to a shipment must be unlinked first — see Logistics Linking.
import agribackup
from agribackup.rest import ApiException

configuration = agribackup.Configuration()
configuration.api_key['ApiKeyAuth'] = 'sk_live_YOUR_API_KEY'

with agribackup.ApiClient(configuration) as api_client:
    try:
        batches_api = agribackup.EnterpriseBatchesApi(api_client)
        batches_api.delete_batch(batch_id="uuid-1234")
        print("Batch deleted.")
    except ApiException as e:
        print("Error:", e)
import { AgriBackupClient } from '@agribackup/sdk';

const client = new AgriBackupClient({ apiKey: 'sk_live_YOUR_API_KEY' });

async function deleteBatch(batchId) {
  try {
    await client.batches.delete(batchId);
    console.log('Batch deleted.');
  } catch (error) {
    console.error('Error:', error.message);
  }
}

deleteBatch('uuid-1234');
curl --request DELETE \
  --url https://live.agribackup.com/api/v1/enterprise/eudr/batches/uuid-1234 \
  --header 'X-API-Key: sk_live_YOUR_API_KEY'
A successful deletion returns 204 No Content.

Batch statuses

status / consolidatedRiskStateMeaning
PENDING_RISK_ASSESSMENTCopernicus risk check in progress
COMPLIANTAll linked polygons passed; batch is clear for logistics
HIGH_RISKOne or more polygons carry a deforestation signal
LOW / MEDIUM / HIGHConsolidated risk level from satellite analysis
NONENo risk detected across all linked polygons
Use GET /api/v1/enterprise/eudr/batches with cursor-based pagination (starting_after parameter) to list all batches for your organization and filter by status.