On this pageHow it works
Some data points live with your suppliers — composition from the cell maker, critical raw materials from the material supplier. A supplier request asks for exactly those fields, and nothing reaches the passport until you accept it.
How it works
- 1
You ask
Create a request for a model with the fields you need — in the app, or with
POST /upload-links. It returns atoken. - 2
They answer
The supplier opens
/u/{token}on the public passport host — no account, no password — and types the requested values or uploads a file. They see and can answer only the fields you asked for. - 3
You are told
A
supplier.submittedwebhook names the request, the model and the fields that arrived, or the file. - 4
You accept
Values stay proposals until you accept them, field by field, with
POST /upload-links/{id}/accept. Accepting writes them to the model and records the supplier as their source.
1. Find what to ask for
The missing-field analysis lists the required fields still empty. Pick the ones a supplier owns and use their name values as requestedFields.
curl "https://dppapi-production.up.railway.app/v1/models/cm1q8x2k40003l70f9a8s7d6e/completeness" \-H "Authorization: Bearer $DPP_API_KEY"2. Send the request
curl -X POST "https://dppapi-production.up.railway.app/v1/upload-links" \-H "Authorization: Bearer $DPP_API_KEY" \-H "Content-Type: application/json" \-H "Idempotency-Key: supplier-cellco-c48-15-2027" \-d '{"supplierName": "Cell Supplier Co.","supplierEmail": "qa@cellsupplier.example","modelId": "cm1q8x2k40003l70f9a8s7d6e","requestedFields": ["criticalRawMaterials","detailedComposition"],"expiresInDays": 30,"message": "Please confirm the cathode composition for the 2027 passport."}'Send the supplier the link /u/{token} on your public passport host, using the token in the response. Links always expire (at most 365 days): the token is a credential that travels in a URL. Never log or forward it beyond the supplier.
3. React to the answer
{"id": "evt_1a2b3c4d5e6f40718293a4b5c6d7e8f9","type": "supplier.submitted","created_at": "2027-02-03T14:21:09.002Z","data": {"request": {"id": "cm1qg5h6j0070l70fr7t8y9u0","supplierName": "Cell Supplier Co.","modelId": "cm1q8x2k40003l70f9a8s7d6e","kind": "values"},"fields": ["detailedComposition", "criticalRawMaterials"]}}For a file, kind is "file" and data.file holds id, filename, mimeType and size instead of fields; list the files with GET /upload-links/{id}/files. Without webhooks, poll GET /upload-links and look for status: "responded" — the proposed values are in submittedValues.
curl "https://dppapi-production.up.railway.app/v1/upload-links" \-H "Authorization: Bearer $DPP_API_KEY"4. Accept
Review the proposed values — you remain accountable for what the passport says — and accept the ones you sign for. Values you leave stay proposed; when nothing is left, the request is finished.
curl -X POST "https://dppapi-production.up.railway.app/v1/upload-links/cm1qg5h6j0070l70fr7t8y9u0/accept" \-H "Authorization: Bearer $DPP_API_KEY" \-H "Content-Type: application/json" \-d '{"fields": ["criticalRawMaterials","detailedComposition"]}'{"accepted": 2,"remaining": 0}Then re-run the missing-field analysis: when the model is complete for its category, its passports can be published. The audit trail records the supplier as the source of each accepted value.
Every endpoint used here is documented under Supplier requests.