JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 18
  • Score
    100M100P100Q56851F
  • License AGPL-3.0-only

Enterprise-grade Node.js library for the EU Deforestation Regulation (EUDR) TRACES system. It provides seamless integration for submitting, amending, retrieving, and managing Due Diligence Statements (DDS) with support for both V1 and V2 APIs.

Package Exports

  • eudr-api-client
  • eudr-api-client/scenarios
  • eudr-api-client/scenarios-v2
  • eudr-api-client/services
  • eudr-api-client/utils

Readme

🌲 EUDR API Client

npm version License: AGPL v3 Node.js Version Test Status

Enterprise-grade Node.js library for EU Deforestation Regulation (EUDR) compliance
Complete integration with EUDR TRACES system for Due Diligence Statements (DDS) management

EUDR Systems

The EUDR system operates on two environments:

  • 🟒 Production (LIVE): https://eudr.webcloud.ec.europa.eu/tracesnt/

    • Purpose: Real submissions with legal value
    • Submission Endpoint: https://eudr.webcloud.ec.europa.eu/tracesnt/ws/EUDRSubmissionServiceV1
    • Web Service Client ID: eudr
    • Use: Only for products to be placed on the market or exported after entry into application
    • Note: Submissions have legal value and can be subject to checks by Competent Authorities
  • 🟑 Acceptance (Training): https://acceptance.eudr.webcloud.ec.europa.eu/tracesnt/

    • Purpose: Training and familiarization platform
    • Submission Endpoint: https://webgate.acceptance.ec.europa.eu/tracesnt/ws/EUDRSubmissionServiceV1
    • Web Service Client ID: eudr-test
    • Use: Testing and getting familiar with the system
    • Note: Submissions have no legal value

Why EUDR API Client?

The EU Deforestation Regulation (EUDR) requires operators and traders to submit Due Diligence Statements for commodities like wood, cocoa, coffee, and more. This library provides:

  • βœ… 100% API Coverage - Both V1 and V2 EUDR APIs fully implemented
  • βœ… Production-Ready - Battle-tested with real EUDR systems
  • βœ… Well-Documented - Comprehensive documentation with real examples
  • βœ… Enterprise Features - Robust error handling, retry logic, and logging
  • βœ… Easy Integration - Simple API with real-world examples

Table of Contents

Quick Start

Installation

npm install eudr-api-client

Basic Setup

const { EudrSubmissionClient } = require('eudr-api-client');

// Initialize the client
const client = new EudrSubmissionClient({
  endpoint: 'https://webgate.acceptance.ec.europa.eu/tracesnt/ws/EUDRSubmissionServiceV1', //acceptance
  //endpoint: https://eudr.webcloud.ec.europa.eu/tracesnt/ws/EUDRSubmissionServiceV1 //production
  username: 'your-username',
  password: 'your-password',
  webServiceClientId: 'eudr-test' //eudr-test = acceptance server, eudr = production server
});

// Submit your first DDS
const result = await client.submitDds({
  operatorType: 'TRADER',
  statement: {
    internalReferenceNumber: 'REF-001',
    activityType: 'TRADE',
    countryOfActivity: 'HR',
    borderCrossCountry: 'HR',
    commodities: [{
      descriptors: {
        descriptionOfGoods: 'Traded wood products',
        goodsMeasure: { netWeight: 20, volume: 15 }
      },
      hsHeading: '4401',
      speciesInfo: {
        scientificName: 'Fagus silvatica',
        commonName: 'European Beech'
      }
    }],
    operator: {
      nameAndAddress: {
        name: 'Your Company Ltd.',
        country: 'HR',
        address: 'Your Address 123, 10000 Zagreb'
      },
      email: 'info@yourcompany.com',
      phone: '+385 1 234 5678'
    },
    geoLocationConfidential: false,
    associatedStatements: [{
      referenceNumber: '25NLSN6LX69730',
      verificationNumber: 'K7R8LA90'
    }]
  }
});

console.log('βœ… DDS Submitted. Identifier:', result.ddsIdentifier);

Real-World Examples

Trade Operations

Scenario: Trading wood products with references to existing DDS statements

const { EudrSubmissionClient } = require('eudr-api-client');

const client = new EudrSubmissionClient({
  endpoint: process.env.EUDR_ENDPOINT,
  username: process.env.EUDR_USERNAME,
  password: process.env.EUDR_PASSWORD,
  webServiceClientId: process.env.EUDR_CLIENT_ID
});

// Trade submission with multiple associated statements
const tradeResult = await client.submitDds({
  operatorType: "TRADER",
  statement: {
    internalReferenceNumber: "DLE20/358",
    activityType: "TRADE",
    countryOfActivity: "HR",
    borderCrossCountry: "HR",
    comment: "Trade submission with multiple associated statements",
    commodities: [{
      descriptors: {
        descriptionOfGoods: "Traded wood products from main warehouse",
        goodsMeasure: {
          netWeight: 20,
          volume: 15
        }
      },
      hsHeading: "4401",
      speciesInfo: {
        scientificName: "Fagus silvatica",
        commonName: "BUKVA OBIČNA"
      }
    }],
    operator: {
      nameAndAddress: {
        name: "GreenWood Solutions Ltd.",
        country: "HR",
        address: "Trg Republike 15, 10000 Zagreb"
      },
      email: "info@greenwood-solutions.hr",
      phone: "+385 (001) 480-4111"
    },
    geoLocationConfidential: false,
    associatedStatements: [
      {
        referenceNumber: "25NLSN6LX69730",
        verificationNumber: "K7R8LA90"
      },
      {
        referenceNumber: "25NLWPAZWQ8865",
        verificationNumber: "GLE9SMMM"
      }
    ]
  }
});

console.log(`βœ… Trade DDS submitted. Identifier: ${tradeResult.ddsIdentifier}`);

Import Operations

Scenario: Importing wood products with geolocation data

// Import submission with producer geolocations
const importResult = await client.submitDds({
  operatorType: "OPERATOR",
  statement: {
    internalReferenceNumber: "DLE20/359",
    activityType: "IMPORT",
    countryOfActivity: "HR",
    borderCrossCountry: "HR",
    comment: "Import with geolocations",
    commodities: [{
      descriptors: {
        descriptionOfGoods: "Imported wood products from France",
        goodsMeasure: {
          netWeight: 30,
          volume: 15
        }
      },
      hsHeading: "4401",
      speciesInfo: {
        scientificName: "Fagus silvatica",
        commonName: "BUKVA OBIČNA"
      },
      producers: [{
        country: "FR",
        name: "French Wood Producer",
        // Base64 encoded GeoJSON polygon
        geometryGeojson: "eyJ0eXBlIjoiRmVhdHVyZUNvbGxlY3Rpb24iLCJmZWF0dXJlcyI6W3sidHlwZSI6IkZlYXR1cmUiLCJnZW9tZXRyeSI6eyJ0eXBlIjoiUG9seWdvbiIsImNvb3JkaW5hdGVzIjpbW1sxNC45NzA0NTk4MzIsNDUuMTkyMzk4MjUyXSxbMTQuOTY5ODU4Mjc1LDQ1LjE4ODM0NDEwNl0sWzE4Ljk2ODIyMzYzMSw0NS4xODY4NjQzMTRdLFsxNC45NjI0NDc0NjQsNDUuMTg1Njg0NTJdLFsxNC45NjM2MzE4MzksNDUuMTkxMTExMzkxXSxbMTQuOTY2MTQ1ODEzLDQ1LjE5MDg2MjIzNF0sWzE0Ljk2NzU4NDQwMyw0NS4xOTIyODAxMDZdLFsxNC45NzA0NTk4MzIsNDUuMTkyMzk4MjUyXV1dfSwicHJvcGVydGllcyI6eyJnamlkIjoiNTgwIiwiZ29kaW5hIjoyMDE2LCJwb3Zyc2luYSI6MzEuMjQsIm96bmFrYSI6IjQyIGEifX1dfQ=="
      }]
    }],
    operator: {
      nameAndAddress: {
        name: "GreenWood Solutions Ltd.",
        country: "HR",
        address: "Trg Republike 15, 10000 Zagreb"
      },
      email: "info@greenwood-solutions.hr",
      phone: "+385 (001) 480-4111"
    },
    geoLocationConfidential: false
  }
});

console.log(`βœ… Import DDS submitted. Identifier: ${importResult.ddsIdentifier}`);

Domestic Production

Scenario: Domestic wood production with multiple species

// Domestic production with multiple commodities
const domesticResult = await client.submitDds({
  operatorType: "OPERATOR",
  statement: {
    internalReferenceNumber: "DLE20/357",
    activityType: "DOMESTIC",
    countryOfActivity: "HR",
    borderCrossCountry: "HR",
    comment: "",
    commodities: [
      {
        descriptors: {
          descriptionOfGoods: "Otprema prostornog drva s glavnog stovariőta (popratnica DLE20/357) - BUKVA OBIČNA",
          goodsMeasure: {
            volume: 20,
            netWeight: 16
          }
        },
        hsHeading: "4401",
        speciesInfo: {
          scientificName: "Fagus silvatica",
          commonName: "BUKVA OBIČNA"
        },
        producers: [{
          country: "HR",
          name: "GreenWood Solutions Ltd.",
          geometryGeojson: "eyJ0eXBlIjoiRmVhdHVyZUNvbGxlY3Rpb24iLCJmZWF0dXJlcyI6W3sidHlwZSI6IkZlYXR1cmUiLCJnZW9tZXRyeSI6eyJ0eXBlIjoiUG9seWdvbiIsImNvb3JkaW5hdGVzIjpbW1sxNC45NzA0NTk4MzIsNDUuMTkyMzk4MjUyXSxbMTQuOTY5ODU4Mjc1LDQ1LjE4ODM0NDEwNl0sWzE4Ljk2ODIyMzYzMSw0NS4xODY4NjQzMTRdLFsxNC45NjI0NDc0NjQsNDUuMTg1Njg0NTJdLFsxNC45NjM2MzE4MzksNDUuMTkxMTExMzkxXSxbMTQuOTY2MTQ1ODEzLDQ1LjE5MDg2MjIzNF0sWzE0Ljk2NzU4NDQwMyw0NS4xOTIyODAxMDZdLFsxNC45NzA0NTk4MzIsNDUuMTkyMzk4MjUyXV1dfSwicHJvcGVydGllcyI6eyJnamlkIjoiNTgwIiwiZ29kaW5hIjoyMDE2LCJwb3Zyc2luYSI6MzEuMjQsIm96bmFrYSI6IjQyIGEifX1dfQ=="
        }]
      },
      {
        descriptors: {
          descriptionOfGoods: "Otprema prostornog drva s glavnog stovariΕ‘ta (popratnica DLE20/357) - BUKVA OSTALE",
          goodsMeasure: {
            volume: 15,
            netWeight: 12
          }
        },
        hsHeading: "4401",
        speciesInfo: {
          scientificName: "Fagus sp.",
          commonName: "BUKVA OSTALE"
        },
        producers: [{
          country: "HR",
          name: "GreenWood Solutions Ltd.",
          geometryGeojson: "eyJ0eXBlIjoiRmVhdHVyZUNvbGxlY3Rpb24iLCJmZWF0dXJlcyI6W3sidHlwZSI6IkZlYXR1cmUiLCJnZW9tZXRyeSI6eyJ0eXBlIjoiUG9seWdvbiIsImNvb3JkaW5hdGVzIjpbW1sxNC45NzA0NTk4MzIsNDUuMTkyMzk4MjUyXSxbMTQuOTY5ODU4Mjc1LDQ1LjE4ODM0NDEwNl0sWzE4Ljk2ODIyMzYzMSw0NS4xODY4NjQzMTRdLFsxNC45NjI0NDc0NjQsNDUuMTg1Njg0NTJdLFsxNC45NjM2MzE4MzksNDUuMTkxMTExMzkxXSxbMTQuOTY2MTQ1ODEzLDQ1LjE5MDg2MjIzNF0sWzE0Ljk2NzU4NDQwMyw0NS4xOTIyODAxMDZdLFsxNC45NzA0NTk4MzIsNDUuMTkyMzk4MjUyXV1dfSwicHJvcGVydGllcyI6eyJnamlkIjoiNTgwIiwiZ29kaW5hIjoyMDE2LCJwb3Zyc2luYSI6MzEuMjQsIm96bmFrYSI6IjQyIGEifX1dfQ=="
        }]
      }
    ],
    operator: {
      nameAndAddress: {
        name: "GreenWood Solutions Ltd.",
        country: "HR",
        address: "Trg Republike 15, 10000 Zagreb"
      },
      email: "info@greenwood-solutions.hr",
      phone: "+385 (001) 480-4111"
    },
    geoLocationConfidential: false
  }
});

console.log(`βœ… Domestic DDS submitted. Identifier: ${domesticResult.ddsIdentifier}`);

Authorized Representatives

Scenario: Submitting on behalf of another operator

// Authorized representative submission
const representativeResult = await client.submitDds({
  operatorType: "OPERATOR",
  statement: {
    internalReferenceNumber: "DLE20/360",
    activityType: "IMPORT",
    operator: {
      // Reference to the actual operator
      referenceNumber: {
        identifierType: "eori",
        identifierValue: "HR123456789"
      },
      nameAndAddress: {
        name: "Croatian Import Company",
        country: "HR",
        address: "Ulica Kneza Branimira 2, 10000 Zagreb"
      },
      email: "contact@croatianimport.hr",
      phone: "+385 (001) 480-4111"
    },
    countryOfActivity: "HR",
    borderCrossCountry: "HR",
    comment: "Import by authorized representative",
    commodities: [{
      descriptors: {
        descriptionOfGoods: "Wood products imported by representative",
        goodsMeasure: {
          netWeight: 25,
          volume: 12
        }
      },
      hsHeading: "4401",
      speciesInfo: {
        scientificName: "Fagus silvatica",
        commonName: "BUKVA OBIČNA"
      },
      producers: [{
        country: "GH",
        name: "Ghana Wood Board",
        geometryGeojson: "eyJ0eXBlIjoiRmVhdHVyZUNvbGxlY3Rpb24iLCJmZWF0dXJlcyI6W3sidHlwZSI6IkZlYXR1cmUiLCJnZW9tZXRyeSI6eyJ0eXBlIjoiUG9seWdvbiIsImNvb3JkaW5hdGVzIjpbW1stMS4xODY0LDYuNTI0NF0sWy0xLjE4NzQsNi41MjQ0XSxbLTEuMTg3NCw2LjUzNDRdLFstMS4xODY0LDYuNTM0NF0sWy0xLjE4NjQsNi41MjQ0XV1dfSwicHJvcGVydGllcyI6eyJuYW1lIjoiR2hhbmEgV29vZCBCb2FyZCJ9fV19"
      }]
    }],
    geoLocationConfidential: false
  }
});

console.log(`βœ… Representative DDS submitted. Identifier: ${representativeResult.ddsIdentifier}`);

API Services

1. Submission Service

Submit, amend, and retract DDS statements.

V1 Client (EudrSubmissionClient)

const { EudrSubmissionClient } = require('eudr-api-client');
const submissionClient = new EudrSubmissionClient(config);

// Submit DDS
const submitResult = await submissionClient.submitDds(requestObject, { rawResponse: false });

// Amend existing DDS
const amendResult = await submissionClient.amendDds(submitResult.ddsIdentifier, updatedStatement);

// Retract DDS
const retractResult = await submissionClient.retractDds(submitResult.ddsIdentifier);

V2 Client (EudrSubmissionClientV2)

const { EudrSubmissionClientV2 } = require('eudr-api-client');
const submissionClientV2 = new EudrSubmissionClientV2(configV2);

// Submit DDS
const submitResultV2 = await submissionClientV2.submitDds(requestObjectV2);

// Amend existing DDS
const amendResultV2 = await submissionClientV2.amendDds(submitResultV2.ddsIdentifier, updatedStatementV2);

// Retract DDS
const retractResultV2 = await submissionClientV2.retractDds(submitResultV2.ddsIdentifier);

2. Retrieval Service

Retrieve DDS information and supply chain data.

const { EudrRetrievalClient } = require('eudr-api-client');
const retrievalClient = new EudrRetrievalClient(config);

// Get DDS info by UUID
const ddsInfo = await retrievalClient.getDdsInfo('some-uuid-string');

// Get DDS info by internal reference
const ddsList = await retrievalClient.getDdsInfoByInternalReferenceNumber('DLE20/357');

// Get full DDS statement by reference and verification number
const fullDds = await retrievalClient.getStatementByIdentifiers('25NLSN6LX69730', 'K7R8LA90');

// Get referenced DDS for supply chain traversal
const referencedDds = await retrievalClient.getReferencedDDS('25NLWPAZWQ8865', 'GLE9SMMM');

3. Echo Service

Test connectivity and authentication.

const { EudrEchoClient } = require('eudr-api-client');
const echoClient = new EudrEchoClient(config);

// Test connection
const response = await echoClient.echo('Hello EUDR');

console.log('Echo response:', response.status);

Configuration

Environment Variables

Create a .env file in your project root:

# EUDR API Credentials
EUDR_TRACES_USERNAME=your-username
EUDR_TRACES_PASSWORD=your-password
EUDR_TRACES_BASE_URL=https://webgate.acceptance.ec.europa.eu
EUDR_WEB_SERVICE_CLIENT_ID=your-client-id

# Optional: Logging
EUDR_LOG_LEVEL=info  # trace, debug, info, warn, error, fatal

Configuration Options

const config = {
  // Required
  endpoint: 'https://webgate.acceptance.ec.europa.eu/tracesnt/ws/EUDRSubmissionServiceV1',
  username: 'your-username',
  password: 'your-password',
  webServiceClientId: 'eudr-test,
  
  // Optional
  soapAction: 'http://ec.europa.eu/tracesnt/eudr/submission',
  timestampValidity: 60,        // seconds (default: 60)
  timeout: 30000              // milliseconds (default: 30000)
};

Advanced Usage

Using V2 API

The V2 API has stricter validation and different field requirements:

const { EudrSubmissionClientV2 } = require('eudr-api-client');

const clientV2 = new EudrSubmissionClientV2({
  endpoint: `${process.env.EUDR_TRACES_BASE_URL}/tracesnt/ws/EUDRSubmissionServiceV2`,
  username: process.env.EUDR_TRACES_USERNAME,
  password: process.env.EUDR_TRACES_PASSWORD,
  webServiceClientId: process.env.EUDR_WEB_SERVICE_CLIENT_ID
});

// V2 requires specific fields based on activity type
const v2Result = await clientV2.submitDds({
  operatorType: "OPERATOR",
  statement: {
    internalReferenceNumber: "DLE20/357",
    activityType: "DOMESTIC",
    operator: {
      operatorAddress: {  // V2 uses operatorAddress instead of nameAndAddress
        name: "GreenWood Solutions Ltd.",
        country: "HR",
        street: "Trg Republike 15",
        postalCode: "10000",
        city: "Zagreb",
        fullAddress: "Trg Republike 15, 10000 Zagreb"
      },
      email: "info@greenwood-solutions.hr",
      phone: "+385 (001) 480-4111"
    },
    countryOfActivity: "HR",
    borderCrossCountry: "HR",
    commodities: [{
      descriptors: {
        descriptionOfGoods: "Wood products",
        goodsMeasure: {
          supplementaryUnit: 20,  // V2 uses supplementaryUnit for DOMESTIC
          supplementaryUnitQualifier: "MTQ"  // Cubic meters
        }
      },
      hsHeading: "4401",
      speciesInfo: {
        scientificName: "Fagus silvatica",
        commonName: "BUKVA OBIČNA"
      },
      producers: [{
        country: "HR",
        name: "GreenWood Solutions Ltd.",
        geometryGeojson: "base64-encoded-geojson"
      }]
    }],
    geoLocationConfidential: false
  }
});

Error Handling

The library provides comprehensive error handling:

try {
  const result = await client.submitDds(ddsData);
  console.log('Success:', result);
} catch (error) {
  if (error.code === 'EUDR_VALIDATION_ERROR') {
    console.error('Validation failed:', error.details);
  } else if (error.code === 'EUDR_AUTH_ERROR') {
    console.error('Authentication failed:', error.message);
  } else if (error.code === 'EUDR_NETWORK_ERROR') {
    console.error('Network error:', error.message);
  } else {
    console.error('Unexpected error:', error);
  }
}

Custom Logging

The library uses a flexible logging system based on Pino. You can control the log level using the EUDR_LOG_LEVEL environment variable.

// logger.js
const { logger, createLogger } = require('eudr-api-client/utils/logger');

// The default logger is exported and used throughout the library
logger.info('Starting EUDR submission');

// You can create a separate logger if needed, but the library clients
// will still use the default one.
const customLogger = createLogger({ 
  level: 'debug',
  name: 'my-app'
});

customLogger.debug('This is a debug message from a custom logger.');

To see detailed logs from the library, set the environment variable:

# Set log level for the current session
export EUDR_LOG_LEVEL=debug

# Run your application
node your-app.js

Batch Operations

Process multiple DDS submissions efficiently:

const submissions = [
  { /* DDS data 1 */ },
  { /* DDS data 2 */ },
  { /* DDS data 3 */ }
];

const results = await Promise.all(
  submissions.map(async (dds) => {
    try {
      return await client.submitDds(dds);
    } catch (error) {
      return { error: error.message, dds };
    }
  })
);

// Process results
results.forEach((result, index) => {
  if (result.error) {
    console.error(`❌ Submission ${index + 1} failed:`, result.error);
  } else {
    console.log(`βœ… Submission ${index + 1} success:`, result.referenceNumber);
  }
});

Writing Tests

const { expect } = require('chai');
const { EudrSubmissionClient } = require('eudr-api-client');

describe('My EUDR Tests', function() {
  let client;
  
  before(function() {
    client = new EudrSubmissionClient(config);
  });
  
  it('should submit DDS successfully', async function() {
    const result = await client.submitDds(testData);
    expect(result).to.have.property('ddsIdentifier');
    expect(result.ddsIdentifier).to.be.a('string');
  });
});

Troubleshooting

Common Issues

1. Authentication Errors

Error: Authentication failed: Invalid credentials

Solution: Verify your username, password, and webServiceClientId are correct.

2. Network Timeouts

Error: Request timeout of 30000ms exceeded

Solution: Increase the timeout in configuration:

const client = new EudrSubmissionClient({
  ...config,
  timeout: 60000  // 60 seconds
});

3. Validation Errors

Error: Validation failed: Missing required field 'borderCrossCountry'

Solution: Check the API version requirements. V1 and V2 have different field requirements.

4. GeoJSON Encoding

Error: Invalid geometryGeojson format

Solution: Ensure GeoJSON is properly Base64 encoded:

const geojson = {
  type: "FeatureCollection",
  features: [/* your features */]
};

const encoded = Buffer.from(JSON.stringify(geojson)).toString('base64');

Debug Mode

Enable detailed logging for troubleshooting:

# Set environment variable
export EUDR_LOG_LEVEL=trace

# Or in your code
process.env.EUDR_LOG_LEVEL = 'trace';

Getting Help

  1. Check the FAQ
  2. Review test examples
  3. Open an issue on GitHub
  4. Contact support: support@eudr-api.eu

Frequently Asked Questions

Q: What's the difference between V1 and V2 APIs?

A: V2 has stricter validation and different field requirements:

  • V2 requires operatorAddress with structured address fields
  • V2 uses supplementaryUnit for DOMESTIC activities
  • V2 requires percentageEstimationOrDeviation when using netWeight

Q: How do I encode GeoJSON data?

A: Use Base64 encoding:

const geojson = { /* your GeoJSON */ };
const encoded = Buffer.from(JSON.stringify(geojson)).toString('base64');

Q: Can I use this library in production?

A: Yes! The library is production-ready and tested against real EUDR systems.

Q: How do I handle rate limiting?

A: The library includes automatic retry logic. You can customize it:

const client = new EudrSubmissionClient({
  ...config,
  retryConfig: {
    retries: 5,
    retryDelay: 2000
  }
});

Q: What HS codes are supported?

A: The EUDR system supports specific HS codes for regulated commodities:

  • Wood: 4401, 4403, 4406, 4407, 4408, 4409, 4410, 4411, 4412, 4413, 4414, 4415, 4416, 4418, 9403, 9406
  • Cocoa: 1801, 1802, 1803, 1804, 1805, 1806
  • Coffee: 0901
  • Palm oil: 1511, 1513
  • Rubber: 4001, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4015, 4016, 4017
  • Soya: 1201, 1208, 1507
  • Cattle: 0102, 0201, 0202, 0206, 4101, 4104, 4107

API Reference

πŸ§ͺ EudrEchoClient

Service for testing connectivity and authentication.

Methods

Method Description Parameters Returns
echo(params) Test service connectivity message (String) Promise with echo response

Detailed Method Reference

echo(params)

const response = await echoClient.echo('Hello EUDR');

// Returns: { message: 'Hello EUDR' }

πŸ“ EudrSubmissionClient

The main client for submitting, amending, and retracting DDS statements (V1 API).

Methods

Method Description Parameters Returns
submitDds(request, options) Submit a new Due Diligence Statement request (Object), options (Object) Promise with DDS identifier
amendDds(ddsIdentifier, statement, options) Amend an existing DDS ddsIdentifier (String), statement (Object), options (Object) Promise with success status
retractDds(ddsIdentifier, options) Retract a submitted DDS ddsIdentifier (String), options (Object) Promise with success status

Detailed Method Reference

submitDds(request, options)

const result = await client.submitDds({
  operatorType: 'TRADER',  // 'OPERATOR' or 'TRADER'
  statement: {
    internalReferenceNumber: 'REF-001',
    activityType: 'TRADE',
    // ... other statement data
  }
}, {
  rawResponse: false  // Set to true to get raw XML response
});

// Returns: { httpStatus: 200, ddsIdentifier: 'uuid-string', raw: 'xml...', parsed: {...} }

amendDds(ddsIdentifier, statement, options)

const result = await client.amendDds(
  'existing-dds-uuid',  // DDS identifier from previous submission
  {
    // Updated statement data
    internalReferenceNumber: 'REF-001-UPDATED',
    // ... other updated fields
  },
  {
    rawResponse: false
  }
);

// Returns: { httpStatus: 200, success: true, message: 'DDS amended successfully' }

retractDds(ddsIdentifier, options)

const result = await client.retractDds(
  'dds-uuid-to-retract',
  {
    debug: true,        // Enable debug logging
    rawResponse: false  // Set to true to get raw XML response
  }
);

// Returns: { httpStatus: 200, success: true, status: 'SC_200_OK', message: 'DDS retracted successfully' }

πŸš€ EudrSubmissionClientV2

The V2 client for submitting, amending, and retracting DDS statements with enhanced validation and structure.

Methods

Method Description Parameters Returns
submitDds(request, options) Submit a new DDS (V2) request (Object), options (Object) Promise with DDS identifier
amendDds(ddsIdentifier, statement, options) Amend existing DDS (V2) ddsIdentifier (String), statement (Object), options (Object) Promise with success status
retractDds(ddsIdentifier, options) Retract DDS (V2) ddsIdentifier (String), options (Object) Promise with success status

Detailed Method Reference

submitDds(request, options)

const result = await clientV2.submitDds({
  operatorType: 'OPERATOR',
  statement: {
    internalReferenceNumber: 'DLE20/357',
    activityType: 'DOMESTIC',
    operator: {
      operatorAddress: {  // V2 uses operatorAddress instead of nameAndAddress
        name: 'GreenWood Solutions Ltd.',
        country: 'HR',
        street: 'Trg Republike 15',
        postalCode: '10000',
        city: 'Zagreb',
        fullAddress: 'Trg Republike 15, 10000 Zagreb'
      },
      email: 'info@greenwood-solutions.hr',
      phone: '+385 (001) 480-4111'
    },
    countryOfActivity: 'HR',
    borderCrossCountry: 'HR',
    commodities: [{
      descriptors: {
        descriptionOfGoods: 'Wood products',
        goodsMeasure: {
          supplementaryUnit: 20,  // V2 uses supplementaryUnit for DOMESTIC
          supplementaryUnitQualifier: 'MTQ'  // Cubic meters
        }
      },
      hsHeading: '4401',
      speciesInfo: {
        scientificName: 'Fagus silvatica',
        commonName: 'BUKVA OBIČNA'
      },
      producers: [{
        country: 'HR',
        name: 'GreenWood Solutions Ltd.',
        geometryGeojson: 'base64-encoded-geojson'
      }]
    }],
    geoLocationConfidential: false
  }
}, {
  rawResponse: false  // Set to true to get raw XML response
});

// Returns: { httpStatus: 200, ddsIdentifier: 'uuid-string', raw: 'xml...', parsed: {...} }

amendDds(ddsIdentifier, statement, options)

const result = await clientV2.amendDds(
  'existing-dds-uuid',  // DDS identifier from previous submission
  {
    // Updated statement data
    internalReferenceNumber: 'DLE20/357-UPDATED',
    // ... other updated fields
  },
  {
    rawResponse: false
  }
);

// Returns: { httpStatus: 200, success: true, message: 'DDS amended successfully' }

retractDds(ddsIdentifier, options)

const result = await clientV2.retractDds(
  'dds-uuid-to-retract',
  {
    debug: true,        // Enable debug logging
    rawResponse: false  // Set to true to get raw XML response
  }
);

// Returns: { httpStatus: 200, success: true, status: 'SC_200_OK', message: 'DDS retracted successfully' }

πŸ” EudrRetrievalClient

Service for retrieving DDS information and supply chain data.

Methods

Method Description Parameters Returns
getDdsInfo(uuids) Get DDS by UUID uuids (String or Array) Promise with DDS details
getDdsInfoByInternalReferenceNumber(internalReferenceNumber) Get DDS by internal reference internalReferenceNumber (String) Promise with DDS
getStatementByIdentifiers(referenceNumber, verificationNumber) Get full DDS statement by reference and verification number referenceNumber (String), verificationNumber (String) Promise with DDS
getReferencedDDS(referenceNumber, verificationNumber) Get referenced DDS for supply chain traversal referenceNumber (String), verificationNumber (String) Promise with DDS

Detailed Method Reference

getDdsInfo(uuids)

const dds = await retrievalClient.getDdsInfo('some-uuid-string');
// or for multiple:
const ddsList = await retrievalClient.getDdsInfo(['uuid-1', 'uuid-2']);

// Returns: Array of DDS info objects

getDdsInfoByInternalReferenceNumber(internalReferenceNumber)

const ddsList = await retrievalClient.getDdsInfoByInternalReferenceNumber('DLE20/357');

// Returns: Array of matching DDS statements

getStatementByIdentifiers(referenceNumber, verificationNumber)

const fullDds = await retrievalClient.getStatementByIdentifiers('25NLSN6LX69730', 'K7R8LA90');

// Returns: Complete DDS object with all details

getReferencedDDS(referenceNumber, verificationNumber)

const referencedDds = await retrievalClient.getReferencedDDS('25NLWPAZWQ8865', 'GLE9SMMM');

// Returns: Referenced DDS object

πŸ“Š Data Types

DDS Statement Structure (V1)

{
  operatorType: 'TRADER' | 'OPERATOR',
  statement: {
    internalReferenceNumber: String,
    activityType: 'TRADE' | 'IMPORT' | 'EXPORT' | 'DOMESTIC',
    countryOfActivity: String,        // ISO country code (e.g., 'HR', 'FR')
    borderCrossCountry: String,       // ISO country code
    comment: String,
    commodities: [{
      descriptors: {
        descriptionOfGoods: String,
        goodsMeasure: {
          netWeight?: Number,         // in kg
          volume?: Number,            // in mΒ³
        }
      },
      hsHeading: String,             // HS code (e.g., '4401')
      speciesInfo: {
        scientificName: String,
        commonName: String
      },
      producers: [{
        country: String,
        name: String,
        geometryGeojson: String      // Base64 encoded GeoJSON
      }]
    }],
    operator: {
      nameAndAddress: {              // V1 API
        name: String,
        country: String,
        address: String
      },
      email: String,
      phone: String
    },
    geoLocationConfidential: Boolean,
    associatedStatements: [{         // For TRADE activities
      referenceNumber: String,
      verificationNumber: String
    }]
  }
}

DDS Statement Structure (V2)

{
  operatorType: 'OPERATOR' | 'TRADER',
  statement: {
    internalReferenceNumber: String,
    activityType: 'TRADE' | 'IMPORT' | 'EXPORT' | 'DOMESTIC',
    operator: {
      operatorAddress: {              // V2 API - structured address
        name: String,
        country: String,
        street: String,
        postalCode: String,
        city: String,
        fullAddress: String
      },
      email: String,
      phone: String
    },
    countryOfActivity: String,
    borderCrossCountry: String,
    comment: String,
    commodities: [{
      descriptors: {
        descriptionOfGoods: String,
        goodsMeasure: {
          supplementaryUnit?: Number, // V2 API - required for DOMESTIC
          supplementaryUnitQualifier?: String, // V2 API - e.g., 'MTQ'
          netWeight?: Number,         // V2 API - requires percentageEstimationOrDeviation
          percentageEstimationOrDeviation?: Number // V2 API - required with netWeight
        }
      },
      hsHeading: String,
      speciesInfo: {
        scientificName: String,
        commonName: String
      },
      producers: [{
        country: String,
        name: String,
        geometryGeojson: String
      }]
    }],
    geoLocationConfidential: Boolean,
    associatedStatements: [{         // For TRADE activities
      referenceNumber: String,
      verificationNumber: String
    }]
  }
}

Response Types

Successful Submission Response (V1):

{
  httpStatus: 200,
  ddsIdentifier: 'uuid-string',
  raw: 'raw-xml-response',
  parsed: { /* parsed XML object */ }
}

Successful Submission Response (V2):

{
  httpStatus: 200,
  ddsIdentifier: 'uuid-string',
  raw: 'raw-xml-response',
  parsed: { /* parsed XML object */ }
}

Contributing

We welcome contributions from the community! If you'd like to contribute, please follow these steps:

  1. Fork the repository on GitHub.
  2. Create a new branch for your feature or bug fix.
  3. Make your changes and commit them with a clear message.
  4. Push your branch and open a pull request.

Please check our GitHub Issues for bug reports and feature requests.

License

This project is dual-licensed. See the LICENCE.md file for details.

  • Open Source (AGPL v3): You can use, modify, and distribute this software under the terms of the GNU AGPL v3. This requires you to release the source code of any derivative works.
  • Commercial License: For use in proprietary applications without the source code disclosure requirements of the AGPL, a commercial license is available. Please contact us at support@eudr-api.eu for more information.

Support

For community support, please open an issue on our GitHub repository.

For commercial support and licensing inquiries, please contact us at support@eudr-api.eu.