๐Ÿ”Œ Enterprise API

Timberlark Enterprise API

Pull your own EUDR compliance records directly into your procurement or ERP software โ€” no manual exports, no waiting on someone to send a PDF. Available on the Business ($399/mo) and EUDR Enterprise ($599/mo) plans.

Getting Your API Key

API keys are generated from your Enterprise Profile โ€” no separate developer account needed. Go to app.timberlark.com/enterprise-profile and scroll to the "API Access" section. If your account is on the Business or EUDR Enterprise plan, you can generate a key immediately.

Your key is shown exactly once at creation time. Store it securely โ€” Timberlark never stores the plaintext key and cannot retrieve it for you if lost. If a key is lost or compromised, revoke it and generate a new one.

Authentication

Every request must include your API key as a Bearer token in the Authorization header:

Authorization: Bearer tl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Requests without a valid, non-revoked key โ€” or from an account whose subscription has lapsed below Business tier โ€” receive a 401 or 403 response.

Rate Limiting

Each API key is limited to 60 requests per rolling 60-second window. Every response includes X-RateLimit-Limit and X-RateLimit-Remaining headers so you can back off before hitting the limit. Exceeding it returns 429 with a Retry-After header (in seconds).

This is generous for polling-based integrations โ€” if you're calling more often than once a second, register a webhook instead and let Timberlark push new records to you.

Endpoints

GET/api/v1/eudr-records

Returns your account's EUDR due diligence records, most recent first โ€” GPS-tagged harvest data, species, certifications, blockchain transaction IDs, and satellite deforestation-check results for every statement you've filed.

ParameterTypeDescription
limitintegerMax records to return. Default 50, max 200.
sinceISO 8601 dateOnly return records created on or after this date โ€” useful for incremental syncs.

Example Request

curl "https://app.timberlark.com/api/v1/eudr-records?limit=20&since=2026-07-01" \
  -H "Authorization: Bearer tl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Client Examples

The API is plain REST/JSON โ€” no SDK install required. Here's the same request in a few common environments:

// Node.js (fetch, built in since Node 18)
const res = await fetch(
  "https://app.timberlark.com/api/v1/eudr-records?limit=20",
  { headers: { Authorization: "Bearer tl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } }
);
if (res.status === 429) {
  const retryAfter = res.headers.get("Retry-After");
  // back off and retry after `retryAfter` seconds
}
const { records } = await res.json();
# Python (requests)
import requests

resp = requests.get(
    "https://app.timberlark.com/api/v1/eudr-records",
    params={"limit": 20},
    headers={"Authorization": "Bearer tl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},
)
resp.raise_for_status()
records = resp.json()["records"]
// C# (HttpClient โ€” common in SAP/Dynamics integrations)
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", "tl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
var response = await client.GetAsync(
    "https://app.timberlark.com/api/v1/eudr-records?limit=20");
var json = await response.Content.ReadAsStringAsync();

Example Response

{
  "fetchedAt": "2026-07-29T14:02:11.000Z",
  "count": 2,
  "limit": 20,
  "records": [
    {
      "id": "b2f1c9a0-...",
      "statement_number": "TL-EUDR-20260703-4821",
      "company_name": "Nordic Timber Exports GmbH",
      "harvest_country": "Sweden",
      "harvest_region": "Norrland",
      "species": "Pine (Pinus spp.); Spruce (Picea spp.)",
      "volume_tons": "480",
      "gps_lat": "65.0987",
      "gps_lng": "16.8321",
      "deforestation_declaration": true,
      "satellite_check": { "clean": true, "alerts": [] },
      "blockchain_record": {
        "txId": "0x7f3a8c2d...",
        "network": "mainnet",
        "explorerUrl": "https://explore.vechain.org/transactions/0x7f3a8c2d...",
        "filedAt": "2026-07-03T14:32:07.000Z"
      },
      "created_at": "2026-07-03T14:32:07.000Z"
    }
  ]
}

GET/api/v1/jobs

Returns your account's own jobs โ€” whether you posted them or are the accepted party fulfilling them โ€” including custody chain, compliance status, and blockchain event data. Same auth, rate limiting, and limit/since parameters as /eudr-records above.

Example Request

curl "https://app.timberlark.com/api/v1/jobs?limit=20" \
  -H "Authorization: Bearer tl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Example Response

{
  "fetchedAt": "2026-08-01T00:02:11.000Z",
  "count": 1,
  "limit": 20,
  "jobs": [
    {
      "id": "9a2c1e40-...",
      "title": "40-acre Loblolly Pine Harvest",
      "location": "Valdosta, GA",
      "commodity_key": "timber",
      "job_type": "logging",
      "status": "in_progress",
      "posted_by": "Jane R.",
      "posted_by_role": "landowner",
      "accepted_by": "Timber Solutions LLC",
      "compliance_type": "eudr",
      "compliance_data": { "statement_number": "TL-EUDR-20260703-4821" },
      "custody_chain": [
        { "step": "harvested", "at": "2026-07-01T10:00:00.000Z", "gps": { "lat": 30.83, "lng": -83.28 } }
      ],
      "vechain_events": [],
      "created_at": "2026-06-28T09:00:00.000Z",
      "updated_at": "2026-07-01T10:00:00.000Z"
    }
  ]
}

Webhooks

Instead of polling GET /api/v1/eudr-records, register a webhook URL from your Enterprise Profile's "Webhooks" section and Timberlark will push a signed notification to it the instant a new EUDR record is filed on your account โ€” no polling required.

Event: eudr_record.created

Fires once, immediately, whenever a new EUDR due diligence statement is filed under your account.

Request

Timberlark sends an HTTP POST to your registered URL with a JSON body and two custom headers:

POST /your-endpoint HTTP/1.1
Content-Type: application/json
X-Timberlark-Event: eudr_record.created
X-Timberlark-Signature: 284ac72efcdef65ffea8d61b00c8a7951d90961e88b372d63216594811dd2609

{
  "event": "eudr_record.created",
  "timestamp": "2026-07-31T00:52:34Z",
  "data": {
    "id": "55b34e9a-7b15-4422-b85a-44e20bda0185",
    "statement_number": "TL-EUDR-20260703-4821",
    "company_name": "Nordic Timber Exports GmbH",
    "harvest_country": "Sweden",
    "species": "Pine (Pinus spp.); Spruce (Picea spp.)",
    "created_at": "2026-07-03T14:32:07.000Z"
  }
}

Verifying the signature

X-Timberlark-Signature is an HMAC-SHA256 of the exact request body, hex-encoded, signed with the secret shown once when you registered the webhook. Verify it before trusting the payload:

// Node.js example
const crypto = require('crypto');

function verify(rawBody, signatureHeader, secret) {
  const expected = crypto.createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signatureHeader)
  );
}

Notes

  • Webhook URLs must be https:// โ€” plain HTTP is not accepted.
  • The signing secret is shown exactly once, at registration. If it's lost, remove the webhook and register a new one to get a fresh secret.
  • A webhook can be paused (without losing its URL/secret) or removed entirely from the Enterprise Profile screen at any time.
  • If your endpoint doesn't respond with a 2xx within 5 seconds, delivery is retried automatically with backoff (roughly 2min, 5min, 15min, then 30min) for up to 5 total attempts over about an hour before we give up. You don't need to build your own retry handling for transient downtime.
  • Even so, webhooks are a convenience, not a guarantee โ€” use GET /api/v1/eudr-records with the since parameter as a periodic backstop to catch anything missed after all retries are exhausted.

Response Status Codes

200Success โ€” records returned.
401Missing, malformed, or revoked API key.
403The key's account no longer has an active Business or EUDR Enterprise subscription.
405Wrong HTTP method โ€” this endpoint only accepts GET.
429Rate limit exceeded (60 requests/60s per key). Check the Retry-After header before retrying.
500Server error โ€” safe to retry with backoff.

Notes for Integrators

  • Responses are never CDN-cached โ€” every request reflects the current state of your compliance data.
  • Up to 5 active API keys are allowed per account at once; revoke unused keys before generating new ones.
  • All GPS coordinates and blockchain data returned are exactly what's on file for your own account โ€” nothing is redacted, since this is your own data.
  • This endpoint is read-only. There is currently no API for creating or modifying compliance records โ€” those are filed through the app to keep the blockchain audit trail consistent.
  • Your call volume (today / last 30 days) and each webhook's recent delivery health are visible on the API Access and Webhooks sections of your Enterprise Profile โ€” no need to build your own logging to know if something's wrong.

Need help integrating?

If your procurement or ERP team needs help wiring this up, reach out directly โ€” we'll work with your developers.

Contact Us โ†’