Developers · AI agents

EPR API for AI agents

Any agent that can make HTTP requests can check obligations, quote and run a full simulated onboarding here, with no key and no account. A person still signs and pays.

By Razvan Toma · Founder · Last checked 1 November 2026

Quick answer

Yes, an AI agent can test this API on its own. It needs HTTP GET and POST and nothing else. A browsing-only agent can read these pages, but it can't run the steps.

What the agent doesEndpointEffect
Check countries and likely streamsPOST /checkReturns data only
Read the France questionsGET /france/questionnaireReturns data only
Quote from live pricesPOST /quoteReturns data only
Simulate each country's stepsPOST /sandbox/onboardingsSimulated, creates nothing
Prepare a checkout link for a personPOST /onboarding-linksReturns a link, nothing is ordered until a person pays

The base URL is https://epreurep.com/api/v1. It takes JSON over HTTPS, with a limit of 30 requests a minute per IP. Prices exclude VAT.

Files to read

FileUse it for
openapi.jsonThe exact contract of every endpoint
This page as MarkdownThis quickstart as plain text
Full documentation as MarkdownEvery rule, field and error
llms.txtAll pages and the facts to quote about EPR EU Rep

Run the full test

These five steps are the whole journey. Each example shows what the live API returned.

1. Check the countries and streams

curl -X POST https://epreurep.com/api/v1/check \
  -H 'content-type: application/json' \
  -d '{"countries":["FR","DE","ES"],"products":["cotton t-shirt","toy car"]}'
{
  "ok": true,
  "countries": [
    { "code": "FR", "covered": true, "name": "France" },
    { "code": "DE", "covered": true, "name": "Germany" },
    { "code": "ES", "covered": true, "name": "Spain" }
  ],
  "streams": ["household-packaging", "textiles-clothing-and-footwear-tlc", "toys"],
  "indicative": true,
  "note": "A first guess from product words. Whether you are the producer depends on your sales channels and establishment."
}

streams is a first guess from the words in products, and indicative is always true. Confirm the streams with the client before you quote.

2. Read the France questions

curl https://epreurep.com/api/v1/france/questionnaire

It returns the three required answers, every stream with its lowest plan, and the plan rules. Ask the client these questions rather than guessing.

3. Get a quote

curl -X POST https://epreurep.com/api/v1/quote \
  -H 'content-type: application/json' \
  -d '{"france":{"sells_to":"consumers","streams":["toys"],"tonnes":"up_to_1"},"germany":{"packaging_kg":{"paper":120,"plastic":40}},"spain":{"plan":"essential","nif":true}}'
{
  "ok": true,
  "custom_quote": false,
  "total": 977,
  "currency": "EUR",
  "lines": [
    { "country": "FR", "item": "France Standard", "eur": 380, "per": "year" },
    { "country": "DE", "item": "Germany packaging", "eur": 149, "per": "year" },
    { "country": "ES", "item": "Spain Essential", "eur": 199, "per": "year" },
    { "country": "ES", "item": "Spanish NIF", "eur": 249, "per": "one-off" }
  ],
  "france": { "plan": "Standard", "streams": ["household-packaging", "toys"], "stream_count": 2, "tonnes": "up_to_1", "why": [] },
  "germany": { "dual_system_estimate": { "eur": 121.43, "year": 2026, "vat_included": true, "charged": "in your client portal, before we accept the LUCID appointment" } },
  "note": "Indicative. Scheme fees and eco-contributions are billed separately at cost. Prices exclude VAT."
}

If custom_quote is true, the order is Enterprise: over 10 tonnes into France, or more than 3 French streams. total is null and only we can quote it.

4. Simulate the onboarding

curl -X POST https://epreurep.com/api/v1/sandbox/onboardings \
  -H 'content-type: application/json' \
  -d '{"countries":["DE"]}'
{
  "ok": true,
  "sandbox": true,
  "id": "sbx_...",
  "countries": [{
    "country": "DE",
    "status": "order_paid",
    "completed": ["order_paid"],
    "next": { "step": "mandate_signed", "client_action_required": true },
    "registration_number": null
  }],
  "complete": false
}

One step moves on every 5 seconds. France has 3 steps, Germany 5 and Spain 4, so Germany finishes after 20 seconds.

ID=$(curl -s -X POST https://epreurep.com/api/v1/sandbox/onboardings \
  -H 'content-type: application/json' -d '{"countries":["DE"]}' | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')
sleep 25
curl -s https://epreurep.com/api/v1/sandbox/onboardings/$ID
{
  "ok": true,
  "sandbox": true,
  "countries": [{
    "country": "DE",
    "status": "registered",
    "completed": ["order_paid", "mandate_signed", "dual_system_paid", "appointed_in_lucid", "registered"],
    "next": null,
    "registration_number": "DE-TEST-0000000000000"
  }],
  "complete": true,
  "note": "Simulated. No order, mandate, payment or registration exists. Test numbers are not valid anywhere."
}

Stop polling when complete is true. The id holds the whole state, so it keeps working and nothing is stored on our side.

5. Prepare the real link

curl -X POST https://epreurep.com/api/v1/onboarding-links \
  -H 'content-type: application/json' \
  -d '{"partner":"northstar","france":{"sells_to":"consumers","streams":["toys"],"tonnes":"up_to_1"},"company":"Example Ltd","email":"owner@example.com"}'
{
  "ok": true,
  "custom_quote": false,
  "url": "https://epreurep.com/checkout/?fr=0&frs=toys&fr_seg=cons&ref=northstar#company=Example+Ltd&email=owner%40example.com",
  "note": "The client confirms the details, signs and pays at this link. Paid orders are tracked to the partner."
}

northstar is a demo code for testing. Partners use their own. Give the link to the person: company and email stay in the URL fragment, which never reaches a server.

Rules for agents

  • Never present a sandbox result as real. Numbers such as DE-TEST-0000000000000 aren't valid anywhere.
  • Never tell a client they are compliant or registered. Only a real register entry shows that.
  • When client_action_required is true, stop and tell the person what they have to do.
  • Don't sign, pay or appoint anyone on a client's behalf. A person does those.
  • Treat /check as a first guess. Who the producer is depends on sales channels and establishment.
  • Don't use a partner code that isn't yours.

What only a person can do

CountrySteps for the client personally
FranceSign the mandate, which can be done online
GermanySign the mandate by hand or with a qualified electronic signature, and name the representative in LUCID
SpainSign the mandate. The power of attorney is then verified, which can take time

Our team does the registrations and declarations, so they run in days, not seconds. More in why EPR registration can't be fully automated.

Errors

Errors return an HTTP status and a body with ok: false, an error code and a message.

StatuserrorWhat to do
400invalid_jsonSend a JSON object
400invalid_requestmessage names the field. Fix it and retry
400unknown_partnerUse a real partner code
404not_foundCheck the path or the sandbox id
405method_not_allowedUse POST on this path
429Wait, then retry

Prompt to give an agent

Paste this into any agent that can make HTTP requests.

Test the EPR EU Rep API from start to finish.
1. Read https://epreurep.com/developers/ai-agents/index.md and https://epreurep.com/developers/openapi.json
2. POST /api/v1/check for a seller of cotton t-shirts in FR, DE and ES.
3. GET /api/v1/france/questionnaire and POST /api/v1/quote with the answers.
4. POST /api/v1/sandbox/onboardings for FR, DE and ES, then poll the id until complete is true.
5. Report each step's status, and which steps need the client personally.
It is a simulation: never present a test number as a real registration.