> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agribackup.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart: Run the Full EUDR Compliance Lifecycle

> Install an AgriBackup SDK and execute all four compliance steps—polygon ingest, batch register, shipment link, and DDS filing—in minutes.

This guide walks you through the complete EUDR compliance lifecycle from first API call to a filed Due Diligence Statement. By the end you will have submitted farm polygons for satellite verification, registered a consolidated commodity batch on the Hedera ledger, linked it to a Bill of Lading, and generated a TRACES NT–compliant DDS — all programmatically.

<Note>
  Run through this quickstart against the **sandbox** environment first. Use an API key prefixed with `sk_test_` so no real Hedera transactions or TRACES NT submissions occur.
</Note>

## Prerequisites

* An AgriBackup account with at least one API key. Generate keys from the [developer console](https://agribackup.com) or via `POST /api/v1/enterprise/api-keys`.
* One of the three supported runtimes: Python 3.9+, Node.js 18+, or Java 17+.

***

## Step 1 — Install the SDK

<Tabs>
  <Tab title="Python">
    ```bash theme={null}
    pip install agribackup-sdk
    ```
  </Tab>

  <Tab title="Node.js">
    ```bash theme={null}
    npm install @agribackup/sdk
    ```
  </Tab>

  <Tab title="Java">
    Add the dependency to your `pom.xml`:

    ```xml theme={null}
    <dependency>
      <groupId>com.agribackup</groupId>
      <artifactId>agribackup-sdk</artifactId>
      <version>1.0.0</version>
    </dependency>
    ```
  </Tab>
</Tabs>

***

## Step 2 — Authenticate

Pass your API key once during client initialization. The SDK reads the `sk_live_` or `sk_test_` prefix and routes all requests to the correct base URL automatically — you never need to hard-code a host.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    import agribackup

    configuration = agribackup.Configuration()
    configuration.api_key['ApiKeyAuth'] = 'sk_test_YOUR_API_KEY'
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    import { AgriBackupClient } from '@agribackup/sdk';

    const client = new AgriBackupClient({
      apiKey: 'sk_test_YOUR_API_KEY'
    });
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.agribackup.client.*;

    ApiClient defaultClient = Configuration.getDefaultApiClient();
    defaultClient.setApiKey("sk_test_YOUR_API_KEY");
    ```
  </Tab>
</Tabs>

Replace `sk_test_YOUR_API_KEY` with the key you generated from the dashboard.

***

## Step 3 — Ingest farm polygons

Submit GeoJSON farm boundaries for satellite deforestation screening. This endpoint is **asynchronous** — it returns `202 Accepted` with a `jobId` immediately. The actual Copernicus screening runs in the background; you receive a `polygon.verified` webhook (or can poll the job endpoint) when screening completes.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    import agribackup
    from agribackup.rest import ApiException

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

    with agribackup.ApiClient(configuration) as api_client:
        polygons_api = agribackup.EnterprisePolygonsApi(api_client)

        req = 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_name": "Global Coffee Farmer #1",
                        "farmer_id": "TEST_FARMER_100",
                        "plot_name": "Nyeri Hill Farm Block B",
                        "area": 2.5,
                        "unit": "HECTARES",
                        "commodity": "Coffee"
                    }
                }
            ]
        )

        polygon_job = polygons_api.ingest_polygons(
            idempotency_key='tx_1001',
            polygon_ingestion_request=req
        )
        print("Polygon job accepted:", polygon_job.job_id)
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    import { AgriBackupClient } from '@agribackup/sdk';

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

    const polygonJob = await client.polygons.ingestFromFile('./farm.geojson', {
      idempotencyKey: 'tx_uuid_1002'
    });

    console.log('Polygon job accepted:', polygonJob.jobId);
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.agribackup.client.*;
    import com.agribackup.client.api.*;
    import com.agribackup.client.model.*;
    import java.util.UUID;

    ApiClient defaultClient = Configuration.getDefaultApiClient();
    defaultClient.setApiKey("sk_test_YOUR_API_KEY");

    EnterprisePolygonsApi polygonsApi = new EnterprisePolygonsApi(defaultClient);
    JobAcceptedResponse polygonJob = polygonsApi.ingestPolygons(
        UUID.randomUUID(), req, null
    );
    System.out.println("Polygon job accepted: " + polygonJob.getJobId());
    ```
  </Tab>
</Tabs>

**Expected response (`202 Accepted`):**

```json theme={null}
{
  "jobId": "job_998877",
  "status": "PENDING",
  "estimatedDurationSec": 3,
  "createdAt": "2026-06-15T12:00:00Z"
}
```

The `Location` response header also points directly to `GET /api/v1/enterprise/eudr/jobs/job_998877` for polling. Wait for the `polygon.verified` webhook or poll until `phase` is `COMPLETED` before proceeding.

***

## Step 4 — Register the consolidated batch

Once your polygons are verified, register a commodity batch that references the polygon IDs. AgriBackup cross-checks the polygon compliance state, triggers a Copernicus risk assessment, and anchors the batch on Hedera. This step is also asynchronous and returns `202 Accepted`.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    import agribackup
    from agribackup.rest import ApiException

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

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

        batch = batches_api.register_batch(
            agribackup.BatchRegistration(
                batch_code='BR-2026-991',
                supplier_id='ERP-VEND-991',
                total_quantity=1500.0,
                unit='KGM',
                harvest_date='2026-07-08',
                valid_polygon_ids=[polygon_job.polygon_id]
            )
        )
        print("Batch registered:", batch.batch_id)
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    const batch = await client.batches.ingest({
      batchCode: 'BR-2026-COCOA-991',
      supplierId: 'ERP-VEND-991',
      totalQuantity: 1500.0,
      unit: 'KGM',
      harvestDate: '2026-07-08',
      validPolygonIds: [polygonJob.polygonId]
    });

    console.log('Batch registered:', batch.batchId);
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.agribackup.client.*;
    import com.agribackup.client.api.*;
    import com.agribackup.client.model.*;
    import java.math.BigDecimal;
    import java.time.LocalDate;

    EnterpriseBatchesApi batchesApi = new EnterpriseBatchesApi(defaultClient);

    BatchResponse batch = batchesApi.registerBatch(
        new BatchRegistration()
            .batchCode("BR-2026-991")
            .supplierId("ERP-VEND-991")
            .totalQuantity(new BigDecimal("1500.0"))
            .unit("KGM")
            .harvestDate(LocalDate.parse("2026-07-08"))
            .addValidPolygonIdsItem(polygonJob.getPolygonId())
    );
    System.out.println("Batch registered: " + batch.getBatchId());
    ```
  </Tab>
</Tabs>

**Expected response (`202 Accepted`):**

```json theme={null}
{
  "jobId": "job_112233",
  "status": "PENDING",
  "estimatedDurationSec": 5,
  "createdAt": "2026-06-15T12:01:00Z"
}
```

***

## Step 5 — Link the shipment (Bill of Lading)

Invoke the Hedera `BATCH_SHIPMENT_GATEKEEPER` smart contract to cryptographically lock the compliant batch to a logistics shipment. Provide the Bill of Lading number so it is permanently recorded on-chain. This emits a `shipment.linked` webhook on consensus.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    import agribackup
    from agribackup.rest import ApiException

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

    with agribackup.ApiClient(configuration) as api_client:
        logistics_api = agribackup.EnterpriseLogisticsApi(api_client)

        logistics_api.link_batch_to_shipment(
            agribackup.ShipmentLinkRequest(
                batch_id=batch.batch_id,
                shipment_reference='BOL-99281744'
            )
        )
        print("Shipment linked — awaiting consensus webhook")
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    await client.logistics.linkBatchToShipment({
      batchId: batch.batchId,
      shipmentReference: 'BOL-99281744'
    });

    console.log('Shipment linked — awaiting consensus webhook');
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.agribackup.client.*;
    import com.agribackup.client.api.*;
    import com.agribackup.client.model.*;

    EnterpriseLogisticsApi logisticsApi = new EnterpriseLogisticsApi(defaultClient);

    logisticsApi.linkBatchToShipment(
        new ShipmentLinkRequest()
            .batchId(batch.getBatchId())
            .shipmentReference("BOL-99281744")
    );
    System.out.println("Shipment linked — awaiting consensus webhook");
    ```
  </Tab>
</Tabs>

***

## Step 6 — Generate the Due Diligence Statement

Generate a TRACES NT–compliant DDS XML document. Provide SHA-256 hashes of your land tenure documents — AgriBackup anchors these hashes on Hedera as legal proof before generating the XML and filing it with TRACES NT.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    import agribackup
    from agribackup.rest import ApiException

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

    with agribackup.ApiClient(configuration) as api_client:
        try:
            declarations_api = agribackup.EnterpriseDeclarationsApi(api_client)

            dds = declarations_api.generate_dds(
                agribackup.DdsRequest(
                    batch_id=batch.batch_id,
                    operator_details={'name': 'Tier 1 Corp', 'country': 'KE'}
                )
            )
            print("DDS Successfully Filed. Reference:", dds.traces_nt_xml)

        except ApiException as e:
            print("Cryptographic Rejection:", e)
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    import { AgriBackupClient } from '@agribackup/sdk';

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

    async function executeComplianceLifecycle() {
      try {
        const dds = await client.declarations.generateDds({
          batchId: batch.batchId,
          operatorDetails: { name: 'Tier 1 Corp', country: 'KE' }
        });

        console.log('DDS Successfully Filed. Reference:', dds.tracesNtXml);
      } catch (e) {
        console.error("Cryptographic Rejection:", e.message);
      }
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.agribackup.client.*;
    import com.agribackup.client.api.*;
    import com.agribackup.client.model.*;

    public class ComplianceExecution {
        public static void main(String[] args) {
            ApiClient defaultClient = Configuration.getDefaultApiClient();
            defaultClient.setApiKey("sk_test_YOUR_API_KEY");

            try {
                EnterpriseDeclarationsApi declarationsApi =
                    new EnterpriseDeclarationsApi(defaultClient);

                DeclarationResponse dds = declarationsApi.generateDds(
                    new DdsRequest()
                        .batchId(batch.getBatchId())
                        .operatorDetails(
                            new OperatorDetails().name("Tier 1 Corp").country("KE")
                        )
                );
                System.out.println("DDS Successfully Filed: " + dds.getTracesNtXml());

            } catch (ApiException e) {
                System.err.println("Cryptographic Rejection: " + e.getResponseBody());
            }
        }
    }
    ```
  </Tab>
</Tabs>

**Expected response (`202 Accepted`):**

```json theme={null}
{
  "jobId": "job_445566",
  "status": "PENDING",
  "estimatedDurationSec": 8,
  "createdAt": "2026-06-15T12:03:00Z"
}
```

When the DDS job completes, you receive a `dds.submitted` webhook containing the TRACES NT reference number and the Hedera consensus transaction ID.

***

## The complete lifecycle at a glance

<CodeGroup>
  ```python Python (full lifecycle) theme={null}
  import agribackup
  from agribackup.rest import ApiException

  # 1. Initialize Cryptographic Authentication
  # Base URL is automatically inferred from the API Key prefix (sk_live_ vs sk_test_)
  configuration = agribackup.Configuration()
  configuration.api_key['ApiKeyAuth'] = 'sk_live_YOUR_API_KEY'

  with agribackup.ApiClient(configuration) as api_client:
      try:
          # 2. Ingest GeoJSON Polygons (Satellite Verification)
          polygons_api = agribackup.EnterprisePolygonsApi(api_client)
          polygon_job = polygons_api.ingest_polygons(idempotency_key='tx_1001', polygon_ingestion_request=req)

          # 3. Register the Consolidated Batch (Upon Oracle Compliance)
          batches_api = agribackup.EnterpriseBatchesApi(api_client)
          batch = batches_api.register_batch(agribackup.BatchRegistration(
              batch_code='BR-2026-991', supplier_id='ERP-VEND-991',
              total_quantity=1500.0, unit='KGM', harvest_date='2026-07-08',
              valid_polygon_ids=[polygon_job.polygon_id]
          ))

          # 4. Link Logistics (Bill of Lading)
          logistics_api = agribackup.EnterpriseLogisticsApi(api_client)
          logistics_api.link_batch_to_shipment(agribackup.ShipmentLinkRequest(
              batch_id=batch.batch_id, shipment_reference='BOL-99281744'
          ))

          # 5. Generate Due Diligence Statement (TRACES NT)
          declarations_api = agribackup.EnterpriseDeclarationsApi(api_client)
          dds = declarations_api.generate_dds(agribackup.DdsRequest(
              batch_id=batch.batch_id, operator_details={'name': 'Tier 1 Corp', 'country': 'KE'}
          ))

          print("DDS Successfully Filed. Reference:", dds.traces_nt_xml)

      except ApiException as e:
          print("Cryptographic Rejection:", e)
  ```

  ```javascript Node.js (full lifecycle) theme={null}
  import { AgriBackupClient } from '@agribackup/sdk';

  // 1. Initialize Cryptographic Authentication
  // Base URL is automatically inferred from the API Key prefix
  const client = new AgriBackupClient({
    apiKey: 'sk_live_YOUR_API_KEY'
  });

  async function executeComplianceLifecycle() {
    try {
      // 2. Ingest GeoJSON Polygons (Satellite Verification)
      const polygonJob = await client.polygons.ingestFromFile('./farm.geojson', {
        idempotencyKey: 'tx_uuid_1002'
      });

      // 3. Register the Consolidated Batch (Upon Oracle Compliance)
      const batch = await client.batches.ingest({
        batchCode: 'BR-2026-COCOA-991', supplierId: 'ERP-VEND-991',
        totalQuantity: 1500.0, unit: 'KGM', harvestDate: '2026-07-08',
        validPolygonIds: [polygonJob.polygonId]
      });

      // 4. Link Logistics (Bill of Lading)
      await client.logistics.linkBatchToShipment({
        batchId: batch.batchId, shipmentReference: 'BOL-99281744'
      });

      // 5. Generate Due Diligence Statement (TRACES NT)
      const dds = await client.declarations.generateDds({
        batchId: batch.batchId,
        operatorDetails: { name: 'Tier 1 Corp', country: 'KE' }
      });

      console.log('DDS Successfully Filed. Reference:', dds.tracesNtXml);

    } catch (e) {
      console.error("Cryptographic Rejection:", e.message);
    }
  }
  ```

  ```java Java (full lifecycle) theme={null}
  import com.agribackup.client.*;
  import com.agribackup.client.api.*;
  import com.agribackup.client.model.*;
  import java.math.BigDecimal;
  import java.time.LocalDate;
  import java.util.UUID;

  public class ComplianceExecution {
      public static void main(String[] args) {
          // 1. Initialize Cryptographic Authentication
          // Base URL is automatically inferred from the API Key prefix
          ApiClient defaultClient = Configuration.getDefaultApiClient();
          defaultClient.setApiKey("sk_live_YOUR_API_KEY");

          try {
              // 2. Ingest GeoJSON Polygons (Satellite Verification)
              EnterprisePolygonsApi polygonsApi = new EnterprisePolygonsApi(defaultClient);
              JobAcceptedResponse polygonJob = polygonsApi.ingestPolygons(UUID.randomUUID(), req, null);

              // 3. Register the Consolidated Batch (Upon Oracle Compliance)
              EnterpriseBatchesApi batchesApi = new EnterpriseBatchesApi(defaultClient);
              BatchResponse batch = batchesApi.registerBatch(
                  new BatchRegistration().batchCode("BR-2026-991").supplierId("ERP-VEND-991")
                  .totalQuantity(new BigDecimal("1500.0")).unit("KGM").harvestDate(LocalDate.parse("2026-07-08"))
                  .addValidPolygonIdsItem(polygonJob.getPolygonId())
              );

              // 4. Link Logistics (Bill of Lading)
              EnterpriseLogisticsApi logisticsApi = new EnterpriseLogisticsApi(defaultClient);
              logisticsApi.linkBatchToShipment(
                  new ShipmentLinkRequest().batchId(batch.getBatchId()).shipmentReference("BOL-99281744")
              );

              // 5. Generate Due Diligence Statement (TRACES NT)
              EnterpriseDeclarationsApi declarationsApi = new EnterpriseDeclarationsApi(defaultClient);
              DeclarationResponse dds = declarationsApi.generateDds(
                  new DdsRequest().batchId(batch.getBatchId())
                  .operatorDetails(new OperatorDetails().name("Tier 1 Corp").country("KE"))
              );

              System.out.println("DDS Successfully Filed: " + dds.getTracesNtXml());

          } catch (ApiException e) {
              System.err.println("Cryptographic Rejection: " + e.getResponseBody());
          }
      }
  }
  ```
</CodeGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/authentication">
    Learn about live vs sandbox keys, base URL resolution, and securing your credentials.
  </Card>

  <Card title="Async Architecture" icon="arrows-rotate" href="/concepts/async-architecture">
    Understand the job and webhook model behind every 202 response.
  </Card>

  <Card title="Cryptographic Evidence" icon="shield-check" href="/concepts/cryptographic-evidence">
    Retrieve and verify Hedera state proofs for auditors and customs authorities.
  </Card>

  <Card title="EUDR Compliance" icon="leaf" href="/concepts/eudr-compliance">
    Understand the regulation your integration must satisfy.
  </Card>
</CardGroup>
