Privacy notice
Last reviewed 2026-09-30. Served live at /privacy.
How eudr.dev processes personal data under Regulation (EU) 2016/679 (GDPR) and, for people in India, the Digital Personal Data Protection Act, 2023 (see the India section below).
Roles
- Controller: the operator running due diligence. Reg. (EU) 2023/1115 imposes the obligation; the operator decides what is processed and why.
- Processor: Vortx AI Private Limited, operating
eudr.dev, acting on the controller's instructions. - Sub-processor:
emem.dev(Vortx AI Private Limited). Receives plot geometry, HS code, country, quantity only. No operator or supplier identity is sent. When switched on, it also reads photos of residue reports and land records from farm visits (see below). - Farm records and buying decisions: the organisation that keeps them (a buyer, trader or operator) is the controller for the farmers, suppliers and inspectors they concern; Vortx AI Private Limited is its processor. We do not use that data for any purpose of our own.
Lawful basis
Art. 6(1)(c) GDPR. Legal obligation. The obligation is the EUDR due diligence duty (Reg. 2023/1115 Arts. 8–12 + Annex II).
That basis covers due diligence only. Farm records, farm visits and buying decisions for markets outside the EU are not required by the EUDR; the organisation that keeps them needs its own basis, usually its contract with the farmer or supplier (Art. 6(1)(b)) or its legitimate interest in buying produce it can sell (Art. 6(1)(f)), and under the DPDP Act consent or a legitimate use. The organisation decides which, and tells the people concerned.
What we process
Per task:
| field | category | why we need it |
|---|---|---|
| Operator name, address, EORI | identifying data (personal when natural-person operator) | required by Annex II point 1 |
| Supplier name and identifier | identifying data | required by Art. 9(1)(e) and (a) |
| Product HS code, description, quantity | commercial metadata | required by Annex II point 2 |
| Plot geolocation (Polygon or Point) | location data; may be personal when it identifies a smallholder | required by Annex II point 3 + Art. 9(1)(d) |
| Country of production, harvest window | regulatory metadata | required by Annex II point 3 + Art. 9(1)(c) |
No special categories (Art. 9 GDPR), no children's data, no behavioural profiles.
Signing in, and authorising an AI assistant
| field | category | why we need it |
|---|---|---|
| Email address | identifying data | the only credential: sign-in is a one-time link, there is no password |
| Session identifier | technical | keeping you signed in; stored as a hash |
| OAuth access and refresh tokens | technical credential | letting an AI assistant act for you without holding your sign-in; stored as a hash, never in the clear |
| The organisation a token acts for | account metadata | so work an assistant does is filed in your records, not an anonymous tenant |
| Statements compiled, and when | usage metadata | counting against the plan allowance, and answering a disputed invoice |
We issue these tokens ourselves. No third-party identity provider is involved. That is a deliberate choice: every obvious candidate sits outside the EEA, and using one would add a processor to the list below and a Chapter V transfer to assess. Authentication stays inside the same database and the same legal person as the rest of your account.
An assistant's access is limited by scope. eudr:read covers checking
plots and reading your own records; eudr:write is needed to compile
and sign a statement, and is granted separately. You can withdraw either
at any time from your dashboard, and a token expires on its own after
thirty days without use.
Support enquiries
| field | category | why we need it |
|---|---|---|
| Email address | identifying data | to answer you |
| Name | identifying data | optional; we do not require it to accept a bug report |
| Your message | whatever you choose to write | to answer you |
Network prefix (/24 or /48) | technical | recognising a flood of automated submissions. Not your full address |
| Browser user-agent | technical | reproducing a bug you report |
We record the enquiry as well as emailing it, so an unanswered message is visible to us as unanswered rather than lost in a mailbox. No third-party spam-filtering or analytics service is involved — in particular no captcha, which would place a processor outside the EEA on the page you use to ask us about data protection.
Farms, farm visits and buying decisions
| field | category | why it is kept |
|---|---|---|
| Farm name, contact, location, field boundaries, crops | identifying and location data about the farmer | the farm record the organisation buys against |
| Visit date and the inspector's name | identifying data about the inspector | who saw the lot, and when |
| Measurements, the farmer's asking price, whether the farmer agreed, substances declared | commercial data about the farmer | the inputs to the buying decision |
| Photos, video, voice notes and documents from the visit | may show people, their voices and their land | evidence of what was seen |
| Each file's SHA-256, and for JPEG photos the capture time and GPS position the camera wrote into the file | technical and location data | checking a file shown later is the one captured, and that it was taken at the visit |
| The buying decision, overrides with their reason, and the arrival outcome | decision data | the answer, why, and whether it proved right |
| The farmer behind a farm: name, registration number, phone, language, how they are paid (a UPI id or an account's last four digits, never a PIN, password or full number), and whether they agreed to be recorded | identity and contact data about the farmer | agreeing a buy, and knowing who is owed |
| Agreements (kg, price, cut window), farm-gate receipts (weights, crates, grade results) and the farmer's ledger (deliveries, advances, payments, deductions) | commercial data about the farmer | what was agreed, received and owed. eudr.dev records payments; it never moves money |
A farmer's details can be erased on request: the name, registration number, phone, language and payment reference are removed, and the amounts stay so the ledger still adds up.
Photos can show people's faces, and voice notes carry voices. Both visit forms ask whether the farmer agreed, and the service refuses photos, video and voice notes from a visit without that recorded yes; the answer is kept with the visit.
People in a visit photo are mosaicked on arrival, on our own server in the EU, before the photo is kept or sent anywhere: a person detector (geo.qa's package, run here) finds them and each is reduced to blocks that cannot be undone. It is a detector, not a guarantee. It does not see a face in a mirror, a person inside a photo in the frame, a name on a shirt or a licence plate. A photo it was unsure about is flagged for a person to check. Video and voice notes are not redacted.
Photo measuring by geo.qa, from 27 September 2026. A visit photo the
farmer agreed to is sent to geo.qa, a service of the same company, Vortx AI.
geo.qa measures finger length, grade, colour stage and dark peel. It runs on
Amazon Web Services in the United States (us-east-1).
- What is sent is the photo's pixels only. Its EXIF, XMP and comments (the location, time and phone) are removed first.
- No name, farm, visit or organisation goes with it.
- geo.qa returns the measurements with a signed receipt, which we check.
- People in the photo are mosaicked on our own server before it is sent.
- Measuring can be switched off at any time, and then no photo is sent.
Farm locations to geo.qa, from 28 September 2026. To pre-screen farms
before a trip, check whether a photo could be of its field, and measure
the distance from a field to water, geo.qa receives a farm's map pin or a
point inside its field: a latitude and longitude, and for a photo check
the time the photo was taken. No farm name, farmer, organisation or price
goes with it; each pin is sent under a number that means nothing outside
the one request. geo.qa reads satellite facts about that point from emem
and returns its answer. The same switch (EUDR_GEOQA_PRESCREEN) stops it.
Residue reports and land records to emem, from 28 September 2026. A
visit form has two places for papers: a residue lab report and a land
record or lease. A photo taken there is sent to emem, which reads its
text (OCR) and returns the rows it found: for a lab report each residue
and its result, for a land record the owner's name, the parcel number,
the area and the place. A land record therefore sends a person's name
to emem. Nothing else goes with the photo: no farm name, farmer,
organisation or price. emem states that its reader keeps nothing; the
signed reading comes back and is kept with the file, and is deleted
with it. We compare the owner with the farmer linked to the farm and the
residues with the limits we hold for the market; emem does neither.
Papers sent anywhere else on the form are stored, not read. One switch
(EUDR_EMEM_DOCS) stops all sending.
Field pairs to geo.qa and emem, only if an organisation turns it on. An organisation can choose to share pairs from its farm gate and visits so that geo.qa and emem can check their readings against what people recorded: the crates typed at the gate against geo.qa's count of the stack photo, the gate's grade against geo.qa's measurements of the lot's photos, and the day a lot was weighed, at the field's emem cells. No name, price, farm, lot or organisation goes with a pair; the place is an emem cell id. The setting is off unless the organisation turns it on, and the feed is read only by the two partners, each with its own key.
Files are stored on the server's disk in the EU (see the processor table). No off-site copy is made yet. A file is kept only if a visit or a supplier's form listed its fingerprint and its bytes match; it is served back only to members of the organisation that holds the farm, and never runs as a web page.
Farm locations and boundaries (never names) are sent to emem.dev to
read satellite data for the field, as for plots.
A buying decision is a recommendation to the organisation, which can override it with a stated reason; nobody is bound by it and it is not made about the farmer as a person. Art. 22 GDPR is therefore not triggered.
Supplier intake
A supplier invited by an organisation can send their plot, harvest details and, optionally, photos, voice notes and papers. The form records how far each invitation got (opened, started, plot entered, submitted, and the reason a submission was refused) as counts and fixed reason codes, never what was typed. The organisation that sent the link is the controller.
Credits and payment
| field | category | why we need it |
|---|---|---|
| Credit balance and ledger (credits bought, spent, when) | account metadata | charging for statements, and answering a disputed charge |
| Razorpay order and payment identifiers, amount and currency | transaction metadata | proving a top-up was paid before crediting it |
Card and contact details are entered into Razorpay's own Checkout and go to Razorpay directly; they never reach our server. We send Razorpay the amount, the currency and our organisation identifier. Razorpay's script is loaded only when someone chooses to pay, not on page view.
Connector surface
The operator can supply a Scenario through three inbound surfaces: the
dashboard form, a CSV upload, or a POST of a GS1 EPCIS 2.0 document.
The CSV and EPCIS connectors parse the payload locally inside the
engine and emit Scenario objects which then run through the same
pipeline as a hand-entered scenario. The connector layer does not
transit the data to any new third party, so the same Art. 6(1)(c)
GDPR basis (legal obligation under Reg. 2023/1115) applies, and the
sub-processor list is unchanged.
Data minimisation
- Logs record
task_id, stage names, state transitions. No operator or supplier identifiers in general logs. - The pipeline event stream is per-task; only the subscribed SSE client receives it.
- The agent sends plot geometry, HS code, country, quantity to
emem.dev. Identities stay in the agent. - No external fonts. Analytics (Google Analytics 4) loads only after explicit cookie consent and defaults to denied — see the Cookies section and the processor table below. No other third-party trackers.
Retention
| layer | retention | basis |
|---|---|---|
| Operator's own archive | 5 years from DDS submission | Reg. 2023/1115 Art. 4(3), Art. 9(1), Art. 12(5) |
| Due diligence statements held on eudr.dev (Annex II body, signed receipt) | 5 years from the statement, then erased by the hourly sweep. When the member who made one deletes their account, the statement stays as the organisation's record, no longer tied to that person, marked with why it is kept and until when | Reg. 2023/1115 Art. 4(3); GDPR Art. 17(3)(b) |
| Supplier submissions (intake links) | 5 years from submission, then erased; a link nobody answered is erased when its sender leaves | Reg. 2023/1115 Art. 9 and Art. 12(5); GDPR Art. 17(3)(b) |
eudr-a2a working memory | configurable, default 7 days | data minimisation, Art. 5(1)(c) GDPR |
| OAuth access tokens | 1 hour | a short life limits what a leaked token reaches |
| OAuth refresh tokens | 30 days from issue, rotated on each use | Art. 5(1)(e); a leaked one is usable at most once |
| Authorization codes | 1 minute, single use | they exist only to be redeemed |
| Answered support enquiries | 2 years | long enough to see a recurring problem, short enough that a 2026 question is not held in 2031 |
| Unanswered support enquiries | kept until answered | deleting a question nobody replied to would destroy the evidence that we failed to reply |
| Usage records (statements counted) | with the account | so a disputed invoice has an answer |
| Farm records, visits, decisions | until the organisation deletes the farm or the visit | the organisation's own buying record |
| Stored files (photos, voice notes, documents) | until the last visit or supplier submission that listed them is deleted or erased | nothing is kept that no record refers to |
| Uploads abandoned part-way | 7 days | time for a phone to come back into signal |
| Supplier-intake step counts | with the invitation | measuring where suppliers stop |
| Credit ledger and payment identifiers | with the account | answering a disputed charge |
An in-process background sweep enforces the 7-day window
(EUDR_TASK_RETENTION_DAYS). After eviction the receipt CID is still
re-derivable from the operator's archived receipt; the agent itself
keeps no trace of the scenario.
Retention sweep. What runs
Hourly the server (a) purges in-memory Task entries older than the
configured horizon, (b) erases statements and supplier submissions past
their five years, and (c) issues a SQL DELETE FROM shipments WHERE created_at < cutoff AND erased_at IS NOT NULL against the SQLite
store. The DB sweep only touches rows that have already been through
controlled erasure (their annex_ii_json / scenario_json are already
NULL); rows still carrying the live operator payload are out of scope
and remain available for the 5-year regulatory audit. The number of
rows evicted in each pass is logged at INFO level (shipment retention sweep) so an operator can confirm the sweep is healthy.
Your rights
| right | how |
|---|---|
| Information (Art. 13/14) | This notice + the engine's compliance audit at COMPLIANCE.md. The engine also serves /privacy live and surfaces every data-source citation in every DDS receipt. |
| Access (Art. 15) | GET /app/api/account/export returns everything we hold on you as a single JSON file — user record, every org you belong to, shipments per org, supplier-intake invites your orgs issued (including the supplier submissions and step counts, never the token hash), farms with their fields, crops, history, visits, decisions and the records of stored files (each with the address to fetch the file), the credit balance and ledger, API keys (hash + last-four only, never the raw key), connectors, payment methods (vault token id only, no card data). |
| Rectification (Art. 16) | Edit your details in the dashboard or re-submit the corrected scenario. The previous task can be erased with DELETE /a2a/tasks/:id. |
| Erasure (Art. 17) | Deleting a farm or a visit (owner or admin) deletes its records and any stored file nothing else refers to. For statements, three paths: (1) DELETE /a2a/tasks/:id scrubs scenario_json + annex_ii_json for one task; (2) DELETE /app/api/account deletes the user row and revokes all sessions; the statements you made and the supplier submissions you collected are your organisation's legal record, so they stay for their five years with your name removed from them, and are erased when those years end (links nobody answered are erased at once); (3) POST /app/api/orgs/:org/suppliers/invites/:id/erase erases one supplier's submission (the operator is the controller for that supplier's data, so this is how a supplier's erasure request is actioned). The audit-aggregate columns (HS code, country, quantity, verdict, receipt CID, DDS reference), the supplier-invite id + timestamps, and the audit-log table are retained for the regulation-mandated record under Art. 17(3)(b) GDPR + EUDR Art. 4(3), 9(1), 12(5). |
| Supplier data (intake portal) | When you submit a plot via a supplier-intake link, the operator who invited you is the controller; eudr.dev is the processor. Send access / rectification / erasure requests to that operator. The operator actions erasure in-app; eudr.dev then scrubs the submission, contact email, and counterparty label, keeping only non-personal audit identifiers. |
| Restriction (Art. 18) | Contact the deployer. Cookie-revocation + signing-out happens client-side; deeper restriction (suspending re-attestation, freezing a record) is operational and handled by the deployer's controller. |
| Portability (Art. 20) | The Art. 15 export is the portability artifact: a single JSON file in a structured, commonly-used, machine-readable format (RFC 8259 JSON) that another controller can import. |
| Object (Art. 21) | The lawful basis is Art. 6(1)(c) (legal obligation), so the absolute Art. 21(1) right to object does not apply. For any processing the deployer ever extends beyond the EUDR mandate (e.g. analytics), Art. 21 applies and the deployer must offer an opt-out. The shipped engine performs no such extended processing. |
| Automated decision-making (Art. 22) | The engine emits a risk verdict from satellite + country-tier signals. The verdict is explainable (every input is on the receipt) and non-final — the operator retains the legal decision to submit. Art. 22 is therefore not triggered, but the engine is built so a human can audit and override at every step. |
| Lodge a complaint | With your national supervisory authority. For EU residents the lead authority depends on the deployer's establishment. |
Requests against eudr.dev should be sent to avijeet@vortx.ai. The endpoints above are also exposed in-app for signed-in users.
Audit-log content (what survives erasure)
The audit_log table records:
- Sign-in events (actor = user id, no IP in clear, no email body in clear)
- Shipment compile events (subject =
sha256(shipment_id || EUDR_AUDIT_SALT)truncated to 16 hex chars. The receipt CID indetails_jsonis the authoritative anchor; the pseudonymised subject lets us replay an audit without exposing a row id that could be used to enumerate live shipments) - API-key issuance and revocation (subject = key id, never the raw key)
- Account-deletion event (subject = the user id at deletion time; the row stays as a tombstone)
No PII is in the audit-log free-text fields. The details_json field carries only counts and identifiers. Salt precedence at boot: EUDR_AUDIT_SALT env-var (operator override) → persistent instance_salt table row (self-seeded on first start, stable across reboots) → per-process random fallback if both are unavailable. The persistent row keeps shipment subject pseudonyms consistent across reboots without the deployer having to manage the secret out-of-band.
Security
- Receipts: ed25519 signature over canonical JSON. CID changes on any byte change; offline verify against the agent pubkey.
- Session cookie:
HttpOnly,Secure,SameSite=Lax,__Host-prefix over HTTPS. - CSRF: cookie-authenticated mutations require
X-Requested-With: eudr-app. - Sign-in rate limit: 5 magic links per email per hour, 30 per IP per hour.
- Magic links: 32 bytes CSPRNG hex, SHA-256 at rest, single use, 15-minute TTL.
- Production: TLS terminator in front,
EUDR_AGENT_PRIVKEY_B64set to a real 32-byte secret (the server refuses to boot with the dev key over HTTPS).
Trusted proxy
The server reads the originating client IP from the direct TCP peer
by default. X-Forwarded-For and X-Real-IP headers are only
honoured when the peer is in the deployer-configured allow-list
EUDR_TRUSTED_PROXY_IPS (comma-separated, IPv4 or IPv6; empty by
default). Without this list set, an attacker could attach any header
and have it logged as their IP. Art. 32 expects forgery defence on
identifiers used for rate-limiting and audit. Behind nginx /
Cloudflare / a load balancer, list the proxy's IP(s) here so the
forwarded address is honoured; everywhere else, leave it empty.
Session re-validation: each authenticated request hashes the current
peer IP and compares it to the hash stored at sign-in. Drift is
logged as a WARN with the first 8 chars of the session id (no IP,
no email). Sessions are not auto-revoked. Mobile users on cellular
networks legitimately change IP, but the drift signal is available
for the deployer's SOC to act on.
Third-party processors and independent controllers
eudr.dev engages a small number of third parties. Some are
processors under Art. 28 GDPR (they process on our instructions);
some are independent controllers (they decide on their own how they
process the data they receive). The split matters for the legal
basis and the data-subject's rights.
Processors (Art. 28 GDPR)
| Name | What it sees | Location | When it runs |
|---|---|---|---|
emem.dev (Vortx AI Private Limited) | plot geometry, HS code, country, quantity (never operator or supplier identity); when switched on, photos of residue reports and land records from visits, which can name the landowner | India / global responders | Every DDS compile; a visit's papers, once each |
| AWS EMEA SARL — compute, database, stored files, SES | everything held by the service, including farm records and stored files; outbound email recipients | eu-north-1 Stockholm, Sweden (one EC2 instance: compute, database, files; and SES) | Always |
| Google Ireland Limited (Google Analytics 4) | pseudonymous visitor identifier (_ga), URL paths visited, basic device class, IP (anonymised before processing) | EU/EEA collection endpoints, onward transfer to Google LLC (US) under the EU-US Data Privacy Framework | Only after the visitor clicks "Accept analytics"; default is denied |
Independent controllers (not our processors)
| Name | What it sees | Location | When it runs |
|---|---|---|---|
| Razorpay Payments Private Limited | the card, bank or UPI details and contact details the payer enters in Razorpay Checkout; the amount, currency and our organisation identifier | Bengaluru, India | When someone buys credits. Razorpay states it is the Data Fiduciary for this data under the DPDP Act (buyer privacy notice); the payer gives it to Razorpay directly |
| TRACES NT (DG ENV, European Commission) | the filed DDS document | Brussels | The operator submits the DDS through TRACES |
PayPal and x402 settlement are supported by the software for other
deployments but are not enabled on eudr.dev.
The full catalogue with lawful-basis routes and the 30-day change-
notice procedure is at /legal/subprocessors.
No other third-party network calls happen during data entry. Leaflet
and Leaflet.Draw are vendored under /console/vendor/. No CDN, no
basemap tile server. The polygon editor draws on a local grid canvas.
emem.dev is a transfer outside the EEA. Data transferred: plot
geometry, HS code, country, quantity. Where a plot polygon is personal
data of a smallholder, the flow is intra-entity remote processing
(eudr.dev and emem.dev are operated by the same legal person), assessed
and protected per the Transfer impact assessment —
identity is stripped at source and Art. 6(1)(c) (the EUDR
due-diligence duty) is the processing basis.
To add a basemap, re-enable L.tileLayer(..) and update this notice
to disclose the new processor.
India (DPDP Act, 2023)
Vortx AI Private Limited is an Indian company, and many of the farmers, suppliers and inspectors in farm records are in India. For them the Digital Personal Data Protection Act, 2023 applies: the organisation that keeps the records is the Data Fiduciary, and Vortx AI is its Data Processor. The DPDP Rules, 2025 were notified in November 2025 and most of their duties (notice, consent, security safeguards, breach reporting, erasure) apply eighteen months after that. We build to them now: every record above can be exported and deleted, and nothing is used for a purpose of ours.
To access, correct or erase your data, or to raise a grievance, ask the organisation that holds your record; they act on it in the app. If you cannot reach them, write to avijeet@vortx.ai.
Cookies
Four strictly-necessary cookies (no consent required under Art. 5(3)
ePrivacy + EDPB Guidelines 2/2023): __Host-eudr_sid (or eudr_sid
on localhost HTTP), eudr_csrf, eudr_locale, and eudr_consent
(records the analytics-consent choice itself). Two analytics cookies
set only after explicit Accept: _ga and _ga_C654QTBTFX (Google
Analytics 4, default denied via Consent Mode v2). Full inventory at
/legal/cookies. The consent banner appears on
the first visit; "Manage cookies" in the footer reopens it.
Contact
Security: avijeet@vortx.ai (see /.well-known/security.txt).
Privacy queries: contact the deployer of the specific instance. The
deployer is the controller.