Sending a file to File Drop
Lesson 24 of 28 8 min read
Walk a partner's developer through getting a token, choosing the JSON or multipart form, and using id and reference so retries never create duplicate Documents.
This lesson is the one to share with a partner's developer, or to work through yourself when testing. It covers the two calls every upload makes, the two ways to send a file, and the one habit that prevents duplicate orders.
Step 1: get an access token
File Drop only accepts an access token from the Supply Lens Authentication Service, obtained with the OAuth 2.0 client credentials grant (a standard way for one system to log in to another with an id and secret).
curl -s https://id.supplylens.co.uk/connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=client_credentials" \
--data-urlencode "client_id=<client_id>" \
--data-urlencode "client_secret=<client_secret>"
The response contains access_token, expires_in (currently 3600 seconds, but always use
the value returned), token_type (Bearer) and scope, which includes file_drop:write.
Reuse the token
Use the same token until it expires. Don't fetch a new one per file. Get a new token when
File Drop returns 401 or before expires_in runs out.
Encode the secret
A secret can contain +, /, = or &. Each value must be URL-encoded, which
--data-urlencode does. Alternatively send the id and secret with HTTP Basic authentication
(-u "<client_id>:<client_secret>"), and leave them out of the body. Don't send scope.
Step 2: send the file
Every upload goes to the same URL, with the token in the Authorization header:
POST https://filedrop.supplylens.co.uk/{integrationTypeId}/{organisationId}
Authorization: Bearer <access_token>
The Content-Type header chooses between two forms:
| Form | Content type | Use it when |
|---|---|---|
| JSON | application/json | The file is JSON |
| Multipart | multipart/form-data | The file is CSV, XML, EDI or text, or the file name matters |
The JSON form
The file is the request body. Everything else goes in the query string.
| type (required) | The Document type, such as order. |
|---|---|
| reference (required) | The reference users see in Supply Lens. Also used to build the file name if fileName is not sent. |
| id (optional) | Your identifier for the file, kept as its external id and used to detect duplicates. |
| fileName (optional) | The file name in Supply Lens. Defaults to the reference plus .json. |
curl -si "https://filedrop.supplylens.co.uk/<integration_type_id>/<organisation_id>?type=order&reference=PO-10001&id=PO-10001" \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
--data-binary @order.json
Supply Lens stores the JSON with indentation: the formatting changes, the data does not.
The multipart form
Everything goes in form parts, and nothing in the query string.
| file (required) | The file itself. The part must have a file name; Supply Lens keeps the file name and the content type you give the part. |
|---|---|
| type (required) | The Document type. |
| reference (optional) | The reference users see. Defaults to the file name. |
| id (optional) | Your identifier for duplicate detection. |
curl -si "https://filedrop.supplylens.co.uk/<integration_type_id>/<organisation_id>" \
-H "Authorization: Bearer <access_token>" \
-F "type=order" \
-F "reference=PO-10001" \
-F "id=PO-10001" \
-F "file=@PO-10001.csv;type=text/csv"
Send one file per request, and let the HTTP client set the multipart Content-Type header
itself, because it must include the boundary.
The id that prevents duplicates
The comparison covers every file the Integration has received for that Document type, including files received by other routes and files sent without an id (whose external id is their file name).
Always send a unique, stable id
Use something like the order number. If a network error leaves the partner unsure whether an upload worked, they can safely send it again: the id stops a second Document being created.
Limits and values
- The whole request must be no larger than 1 MB (1,048,576 bytes), including multipart
boundaries. Larger requests get
413. typeis case-sensitive lowercase from a fixed list, includingorder,warehouse-order,shipment,warehouse-shipment,goods-inbound,goods-inbound-receipt,inventory,stock-adjustment,invoiceandcustom, among others. Supply Lens tells you which types your Integration accepts.
Sandpiper's 3PL retries safely
The 3PL's system sends each despatch as a CSV with the multipart form, type set to
warehouse-shipment, reference and id set to the despatch number. One afternoon a
timeout means it never sees the response for despatch D-5531 and sends it again. The second
attempt returns 400 saying the file is a duplicate, and Sandpiper still has exactly one
Warehouse Shipment for D-5531.
Recap
- Get a token with the client credentials grant, URL-encode the values and reuse the token until it expires.
- POST to /integrationTypeId/organisationId with a Bearer token.
- JSON form: body is the file, type and reference in the query string. Multipart: everything in form parts, and the file part needs a file name.
- A unique, stable id makes retries safe; without one, every upload is converted.
- Keep requests under 1 MB and use lowercase Document type values.
Quick guides for this topic
Your progress is saved in this browser. Create a free account to keep it everywhere, take quizzes and earn certificates.