Working with files

premote stores three kinds of documents against your trips and travelers:

  • Generated compliance documents — created automatically by premote's workflows after a trip is submitted: A1 certificates and other social security requests and authority replies, posted-worker notification confirmations, and social security statements.
  • Uploaded documents — files you or your travelers attach to a trip or a traveler profile (passports, ID cards, residence permits, insurance documents).
  • On-demand documents — generated the moment you request them: risk assessment reports, health insurance confirmations, and trip data exports.

This guide walks through retrieving each kind, plus uploading your own files.

📘

Before you start

All requests need a bearer token — see Authentication. The bulk endpoints (/trips/download/files, /trips/download/data, /trips/exports) require an API user with an admin or admin-viewer role.

How files work

Three things to know before you integrate:

  1. Generated documents appear asynchronously. Submitting a trip kicks off workflows that file requests with the relevant authorities and store the resulting documents against the trip. A certificate is only retrievable once its workflow has completed successfully — until then, the file simply isn't there yet (see Handling "not ready yet" below). Poll for it; there is currently no file webhook.
  2. Download links are short-lived. Every download URL the API hands back is a signed URL valid for 5 minutes. Request a fresh link each time you need the file — never store the URL itself.
  3. Files carry a type. Each file has a fileType telling you what it is:
fileTypeWhat it is
SSN_REQUESTSocial security request submitted to an authority (e.g. an A1 application)
SSN_REPLYThe authority's reply — e.g. the issued A1 certificate
NOTIFICATION_REQUESTPosted-worker (PWD) notification submitted to an authority
NOTIFICATION_REPLYConfirmation returned for a posted-worker notification
SOCIAL_SECURITY_STATEMENTSocial security statement generated for a trip
RISK_ASSESSMENTRisk assessment report
INSURANCEInsurance document
PASSPORT, ID_CARD, PERMANENT_RESIDENCETraveler identity documents (uploaded)
USER_UPLOADAny other file a user attached
TRIP_EXPORTGenerated trip data export (see step 5)
MISCAnything else

1. Download all files for selected trips

POST /trips/download/filesAPI Reference

Returns the generated compliance documents for the trips you select, bundled as a ZIP. The response is the binary ZIP stream itself — not JSON — so write it straight to disk:

curl -X POST "https://api.premote.io/v1/trips/download/files?type=BUSINESS_TRIP" \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}' \
  --output trip-files.zip
import { writeFile } from 'node:fs/promises'

const res = await fetch(
  'https://api.premote.io/v1/trips/download/files?type=BUSINESS_TRIP',
  {
    method: 'POST',
    headers: {
      Authorization: 'Bearer <token>',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({}),
  },
)
if (!res.ok) throw new Error(`Download failed: ${res.status}`)

// The body is binary — read it as bytes, never as text
await writeFile('trip-files.zip', Buffer.from(await res.arrayBuffer()))

If your HTTP client defaults to text decoding (axios, got), request the response as a buffer or stream instead (e.g. axios' responseType: 'arraybuffer') — decoding the ZIP as text corrupts the archive irrecoverably.

  • selectedTrips (body, optional) — narrow the download to specific trips, e.g. {"selectedTrips": [<tripId>, <tripId>]}. Omit the field to include every trip of the selected type. Note: an empty array ("selectedTrips": []) selects no trips and returns 404 — leave the field out entirely instead.
  • filters (query, optional) — same shape as the trips list filters (e.g. startDate / endDate) to select by date range.
  • type (query) — the trip type to include. Ignored when fetchLive=true (see step 2).
🚧

The ZIP contains generated documents only

This endpoint bundles documents produced by premote's workflows (certificates, confirmations, authority replies). Files uploaded by users are not included — retrieve those individually (step 3).

Handling "not ready yet"

If none of the selected trips have a successfully generated document yet, the endpoint returns 404 "No files for this trip". That's the expected state right after trip submission, while workflows are still running — treat it as "try again later", not as an error in your integration.


2. Get the latest files for ongoing trips with fetchLive

Pass fetchLive=true to skip trip selection by type and instead target trips that are currently underway — approved trips whose travel dates contain today:

curl -X POST "https://api.premote.io/v1/trips/download/files?fetchLive=true" \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}' \
  --output live-trip-files.zip

Use this when you want the current compliance documents for everyone traveling right now — e.g. a daily sync into your HR system.

📘

What fetchLive does — and doesn't — do

fetchLive selects which trips are included: approved trips with start date ≤ today ≤ end date. It does not trigger a new retrieval from the authorities — documents are generated asynchronously by premote's workflows, and this endpoint always serves the latest stored version. When fetchLive=true, the type parameter is ignored.


3. Get a download link for an individual file

GET /files/{key}API Reference

Trip responses (e.g. GET /trips/{id}) include the trip's files with their metadata (id, fileName, fileType, and a path). The path is a link of the form https://api.premote.io/v1/files/{key} — resolve it to get the actual download:

# Default: 302-redirects to the signed download URL — -L follows it
curl -L "https://api.premote.io/v1/files/{key}" \
  -H 'Authorization: Bearer <token>' \
  --output a1-certificate.pdf

# Or fetch the signed URL itself as plain text
curl "https://api.premote.io/v1/files/{key}?redirect=false" \
  -H 'Authorization: Bearer <token>'

The returned URL is valid for 5 minutes; request a fresh one per download.


4. Generate documents on demand

Three document types are generated at request time and returned as a signed download link:

DocumentEndpoint
Social security statementGET /trips/{tripId}/download-statementAPI Reference
Risk assessment reportGET /risk-rules/{tripId}/download-assessmentAPI Reference
Health insurance documentGET /trips/{tripId}/download-health-insuranceAPI Reference
curl "https://api.premote.io/v1/trips/{tripId}/download-statement" \
  -H 'Authorization: Bearer <token>'
📘

Health insurance documents are only available for international trips — the endpoint returns 400 for domestic trips.


5. Export trip data

POST /trips/download/dataAPI Reference

For spreadsheet-style exports of trip data (rather than documents). It accepts the same selectedTrips / type / fetchLive / filters parameters as step 1, queues the export, and returns a jobId.

Then poll GET /trips/exportsAPI Reference — to pick up the finished file:

curl "https://api.premote.io/v1/trips/exports?jobId=<jobId>" \
  -H 'Authorization: Bearer <token>'

Each export entry includes a signed url (valid 5 minutes). Exports remain listed for 7 days.


6. Upload a file

Uploads are a two-step handshake — the API hands you a pre-signed upload URL, and you PUT the file bytes directly to storage.

Step A — request an upload URL. Scope the file to a trip with PUT /trips/file (API Reference), to a traveler with PUT /users/file (API Reference), or use the generic POST /files/signed-upload (API Reference):

curl -X PUT https://api.premote.io/v1/trips/file \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "fileName": "assignment-letter.pdf",
    "fileType": "USER_UPLOAD",
    "tripId": <tripId>
  }'

Response:

{
  "id": 1024,
  "url": "https://files.premote.io/7/assignment-letter.pdf?X-Amz-Signature=..."
}

Step B — upload the bytes to the returned url within 5 minutes:

curl -X PUT "<url from step A>" \
  -H 'Content-Type: application/pdf' \
  --data-binary @assignment-letter.pdf
📘

Network blocks direct uploads?

If your environment blocks direct-to-storage uploads (e.g. a CASB or restrictive proxy), use POST /users/file/upload (API Reference) instead — a multipart upload streamed through the API (max 25 MB).


Recap

StepActionEndpoint
1Download files for selected trips (ZIP)POST /trips/download/files
2Files for currently ongoing tripsPOST /trips/download/files?fetchLive=true
3Download link for a single fileGET /files/{key}
4On-demand documents (statement / risk / insurance)GET /trips/{tripId}/download-statement etc.
5Trip data exportPOST /trips/download/dataGET /trips/exports
6Upload a filePUT /trips/filePUT to signed URL

Did this page help you?