Skip to main content
DELETE
/
api
/
v1
/
enterprise
/
eudr
/
shipments
/
{batchId}
/
shipment
/
{shipmentId}
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.EnterpriseLogisticsApi(api_client)
        response = api_instance.unlink_shipment()
        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.logistics.unlinkShipment();
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");

EnterpriseLogisticsApi apiInstance = new EnterpriseLogisticsApi(defaultClient);
try {
Object result = apiInstance.unlinkShipment();
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 EnterpriseLogisticsApi(config);
try {
var result = await apiInstance.UnlinkShipmentAsync();
Console.WriteLine(result);
} catch (ApiException e) {
Console.WriteLine("Exception when calling API: " + e.Message);
}
}
}
curl --request DELETE \
--url https://live.agribackup.com/api/v1/enterprise/eudr/shipments/{batchId}/shipment/{shipmentId} \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'X-API-Key: <api-key>'
const options = {
method: 'DELETE',
headers: {'Idempotency-Key': '<idempotency-key>', 'X-API-Key': '<api-key>'}
};

fetch('https://live.agribackup.com/api/v1/enterprise/eudr/shipments/{batchId}/shipment/{shipmentId}', 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/shipments/{batchId}/shipment/{shipmentId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_HTTPHEADER => [
"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"
"net/http"
"io"
)

func main() {

url := "https://live.agribackup.com/api/v1/enterprise/eudr/shipments/{batchId}/shipment/{shipmentId}"

req, _ := http.NewRequest("DELETE", url, nil)

req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("X-API-Key", "<api-key>")

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/shipments/{batchId}/shipment/{shipmentId}")

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

request = Net::HTTP::Delete.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["X-API-Key"] = '<api-key>'

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"
}
]
}
Asynchronously rolls back the Hedera smart contract lock that binds a batch to a specific shipment, freeing the batch for reassignment to a new shipment. This operation is essential for logistics cancellations or port-level diversions where a new Bill of Lading must be issued. Because the EVM rollback requires Hedera consensus, the endpoint returns 202 Accepted immediately with a jobId. Poll GET /api/v1/enterprise/eudr/jobs/{jobId} to confirm the rollback has completed before attempting to re-link the batch.
This operation cannot be performed on batches that have already been submitted to TRACES NT. Contact AgriBackup support if you need to revoke a submitted Due Diligence Statement.

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 response without re-invoking the rollback.

Path Parameters

ParameterTypeRequiredDescription
batchIdstringThe UUID of the EUDR batch to unlink.
shipmentIdstringThe shipment reference ID to remove the link from.

Response — 202 Accepted

FieldTypeDescription
jobIdstringUse this ID to poll rollback status via GET /api/v1/enterprise/eudr/jobs/{jobId}.
statusstringAlways PENDING on acceptance.
estimatedDurationSecintegerEstimated seconds until the Hedera rollback transaction reaches consensus.
createdAtstring (ISO-8601)Timestamp when the job was accepted.
{
  "jobId": "job_998877",
  "status": "PENDING",
  "estimatedDurationSec": 3,
  "createdAt": "2026-06-15T12:00:00Z"
}

Error Responses

StatusMeaning
400Invalid batchId or shipmentId.
401Missing or invalid X-API-Key.
403The batch has been submitted to TRACES NT and the link cannot be rolled back.
404No active link found between the given batchId and shipmentId.

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.EnterpriseLogisticsApi(api_client)

        response = api_instance.unlink_shipment(
            idempotency_key=str(uuid.uuid4()),
            batch_id='uuid-1234',
            shipment_id='SHIP-OOCL-9988'
        )
        print("Rollback 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 unlinkShipment(batchId, shipmentId) {
  try {
    const response = await client.logistics.unlinkShipment({
      idempotencyKey: uuidv4(),
      batchId,
      shipmentId
    });
    console.log('Rollback job accepted:', response.jobId);
  } catch (error) {
    console.error('Error:', error.message);
  }
}

unlinkShipment('uuid-1234', 'SHIP-OOCL-9988');
curl -X DELETE \
  "https://live.agribackup.com/api/v1/enterprise/eudr/shipments/uuid-1234/shipment/SHIP-OOCL-9988" \
  -H "X-API-Key: sk_live_YOUR_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

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.

Path Parameters

batchId
string
required
shipmentId
string
required

Response

Smart contract unlock initiated asynchronously

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"