Skip to main content
POST
/
api
/
v1
/
enterprise
/
eudr
/
polygons
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.EnterprisePolygonsApi(api_client)
        response = api_instance.ingest_polygons()
        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.polygons.ingestPolygons();
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");

EnterprisePolygonsApi apiInstance = new EnterprisePolygonsApi(defaultClient);
try {
Object result = apiInstance.ingestPolygons();
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 EnterprisePolygonsApi(config);
try {
var result = await apiInstance.IngestPolygonsAsync();
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/polygons \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'X-API-Key: <api-key>' \
--data '
{
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
36.8,
-1.2
],
[
36.9,
-1.2
],
[
36.9,
-1.3
],
[
36.8,
-1.3
],
[
36.8,
-1.2
]
]
]
},
"properties": {
"farmer_name": "Global Coffee Farmer #1",
"farmer_id": "TEST_FARMER_100",
"plot_name": "Nyeri Hill Farm Block B",
"area": 2.5,
"unit": "HECTARES",
"commodity": "Coffee"
}
}
]
}
'
const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
'X-API-Key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
features: [
{
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [[[36.8, -1.2], [36.9, -1.2], [36.9, -1.3], [36.8, -1.3], [36.8, -1.2]]]
},
properties: {
farmer_name: 'Global Coffee Farmer #1',
farmer_id: 'TEST_FARMER_100',
plot_name: 'Nyeri Hill Farm Block B',
area: 2.5,
unit: 'HECTARES',
commodity: 'Coffee'
}
}
]
})
};

fetch('https://live.agribackup.com/api/v1/enterprise/eudr/polygons', 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/polygons",
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([
'features' => [
[
'type' => 'Feature',
'geometry' => [
'type' => 'Polygon',
'coordinates' => [
[
[
36.8,
-1.2
],
[
36.9,
-1.2
],
[
36.9,
-1.3
],
[
36.8,
-1.3
],
[
36.8,
-1.2
]
]
]
],
'properties' => [
'farmer_name' => 'Global Coffee Farmer #1',
'farmer_id' => 'TEST_FARMER_100',
'plot_name' => 'Nyeri Hill Farm Block B',
'area' => 2.5,
'unit' => 'HECTARES',
'commodity' => 'Coffee'
]
]
]
]),
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/polygons"

payload := strings.NewReader("{\n \"features\": [\n {\n \"type\": \"Feature\",\n \"geometry\": {\n \"type\": \"Polygon\",\n \"coordinates\": [\n [\n [\n 36.8,\n -1.2\n ],\n [\n 36.9,\n -1.2\n ],\n [\n 36.9,\n -1.3\n ],\n [\n 36.8,\n -1.3\n ],\n [\n 36.8,\n -1.2\n ]\n ]\n ]\n },\n \"properties\": {\n \"farmer_name\": \"Global Coffee Farmer #1\",\n \"farmer_id\": \"TEST_FARMER_100\",\n \"plot_name\": \"Nyeri Hill Farm Block B\",\n \"area\": 2.5,\n \"unit\": \"HECTARES\",\n \"commodity\": \"Coffee\"\n }\n }\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/polygons")

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 \"features\": [\n {\n \"type\": \"Feature\",\n \"geometry\": {\n \"type\": \"Polygon\",\n \"coordinates\": [\n [\n [\n 36.8,\n -1.2\n ],\n [\n 36.9,\n -1.2\n ],\n [\n 36.9,\n -1.3\n ],\n [\n 36.8,\n -1.3\n ],\n [\n 36.8,\n -1.2\n ]\n ]\n ]\n },\n \"properties\": {\n \"farmer_name\": \"Global Coffee Farmer #1\",\n \"farmer_id\": \"TEST_FARMER_100\",\n \"plot_name\": \"Nyeri Hill Farm Block B\",\n \"area\": 2.5,\n \"unit\": \"HECTARES\",\n \"commodity\": \"Coffee\"\n }\n }\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"
}
]
}
Submit a batch of farm boundary polygons as GeoJSON Features for EUDR deforestation screening. Because satellite analysis and Hedera DLT anchoring run asynchronously, this endpoint returns 202 Accepted immediately along with a jobId. Poll GET /api/v1/enterprise/eudr/jobs/{jobId} or listen for the polygon.verified webhook to confirm that verification has completed before referencing the polygon IDs in a batch.

Request Headers

HeaderRequiredDescription
X-API-KeyYour live API key, e.g. sk_live_.... Generate one in the AgriBackup dashboard.
Idempotency-KeyA UUID v4 string. Replaying the same key within 24 hours returns the original response without re-queuing the job.
X-Sub-Organization-IDOptional subsidiary identifier to scope polygon data to a specific business unit.

Request Body

Send a JSON object with a single features array. Each element is a GeoJSON Feature with a Polygon geometry and a properties object describing the plot.
{
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [36.8, -1.2],
            [36.9, -1.2],
            [36.9, -1.3],
            [36.8, -1.3],
            [36.8, -1.2]
          ]
        ]
      },
      "properties": {
        "farmer_name": "Global Coffee Farmer #1",
        "farmer_id": "FARM-KE-001",
        "plot_name": "Nyeri Hill Farm Block B",
        "area": 2.5,
        "unit": "HECTARES",
        "commodity": "Coffee"
      }
    }
  ]
}
The features array accepts 0–5,000 items per request. Exceeding 5,000 items returns 413 Payload Too Large.

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 the verification pipeline 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 — polygon.verified Webhook

When verification finishes, AgriBackup fires a polygon.verified event to your registered webhook URL. The payload is signed with X-AgriBackup-Signature (HMAC-SHA256). Polygons that pass screening receive eudrStatus: COMPLIANT and can immediately be referenced in batch registrations.

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

        request = agribackup.PolygonIngestionRequest(
            features=[
                {
                    "type": "Feature",
                    "geometry": {
                        "type": "Polygon",
                        "coordinates": [
                            [[36.8, -1.2], [36.9, -1.2],
                             [36.9, -1.3], [36.8, -1.3], [36.8, -1.2]]
                        ]
                    },
                    "properties": {
                        "farmer_id": "FARM-KE-001",
                        "commodity": "Coffee",
                        "area": 2.5,
                        "unit": "HECTARES"
                    }
                }
            ]
        )

        response = api_instance.ingest_polygons(
            idempotency_key=str(uuid.uuid4()),
            polygon_ingestion_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 ingestPolygons() {
  try {
    const response = await client.polygons.ingestPolygons({
      idempotencyKey: uuidv4(),
      features: [
        {
          type: 'Feature',
          geometry: {
            type: 'Polygon',
            coordinates: [
              [[36.8, -1.2], [36.9, -1.2],
               [36.9, -1.3], [36.8, -1.3], [36.8, -1.2]]
            ]
          },
          properties: {
            farmerId: 'FARM-KE-001',
            commodity: 'Coffee',
            area: 2.5,
            unit: 'HECTARES'
          }
        }
      ]
    });
    console.log('Job accepted:', response.jobId);
  } catch (error) {
    console.error('Error:', error.message);
  }
}
curl -X POST https://live.agribackup.com/api/v1/enterprise/eudr/polygons \
  -H "X-API-Key: sk_live_YOUR_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "features": [
      {
        "type": "Feature",
        "geometry": {
          "type": "Polygon",
          "coordinates": [
            [[36.8,-1.2],[36.9,-1.2],[36.9,-1.3],[36.8,-1.3],[36.8,-1.2]]
          ]
        },
        "properties": {
          "farmer_id": "FARM-KE-001",
          "commodity": "Coffee",
          "area": 2.5,
          "unit": "HECTARES"
        }
      }
    ]
  }'

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 to ingest GeoJSON polygons conforming to RFC 7946

features
object[]
required

Array of GeoJSON Features representing farm boundaries

Maximum array length: 5000

Response

Polygon ingestion accepted and queued for verification

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"