secdl Secure Document Exchange

API Reference

Programmatically submit PDF reports, receive a signed download URL and single-use access password, and let recipients retrieve the document via browser or curl. All endpoints require mutual TLS 1.3 and an API key. EU residency — data never leaves Frankfurt (PROD-EU-2).

Overview

The API has three verbs: upload a document, download a document, and revoke a link. A successful upload returns a one-time URL and a one-time password. We hash the password with Argon2id and discard the plaintext immediately — it cannot be retrieved later. If a recipient loses the password, generate a new one with the revoke-and-reissue endpoint.

Base URL
https://api.secdl.portal42.cc/v2
Auth
Bearer API key + mutual TLS
Content type
application/pdf uploads · application/json responses
Max upload
250 MB per document
Retention
Until expiry + 30 days, then cryptographic erasure

Authentication

Every request must include an Authorization: Bearer <key> header. API keys are scoped per issuing organization and rotate every 180 days.

shell
# Store your key securely — environment variable or secret manager
export SECDL_API_KEY="sk_live_7fA3…Bv21"

Upload a document

POST /v2/documents

Upload a PDF and set access controls. The response includes a download URL and a one-time password — surface both to the recipient (typically in separate channels: URL via email, password via SMS or chat).

Request parameters

FieldTypeRequiredDescription
filebinaryyesThe PDF payload. Multipart form field.
titlestringyesHuman-readable report title shown on the download page.
recipient_namestringyesDisplayed on the download page as confirmation of intended recipient.
recipient_emailstringyesUsed only for password reissue requests; never receives the initial password.
expires_indurationnoISO-8601 duration. Default P7D (7 days). Max P90D.
max_downloadsintegernoDefault 1. Set higher for multi-retrieval links.
metadataobjectnoFree-form key/value pairs mirrored back on retrieval.

Example request

curl · upload
curl -X POST https://api.secdl.portal42.cc/v2/documents \
  -H "Authorization: Bearer $SECDL_API_KEY" \
  -F file=@./q1-audit-report.pdf;type=application/pdf \
  -F title="Q1 2026 Financial Statements & Audit Report" \
  -F recipient_name="Frauke Lindqvist" \
  -F recipient_email="f.lindqvist@nordhafen.ag" \
  -F expires_in="PT24H" \
  -F max_downloads="1"

Example response 201 Created

json
{
  "id": "SDL-2026-0423-AC4F",
  "download_url": "https://secdl.portal42.cc/d/SDL-2026-0423-AC4F",
  "password": "R4TA-9XPM-KQV7-B2LD-ZN8E",  // shown ONCE — not retrievable later
  "sha256": "e3b0c44298fc1c149afbf4c8996fb924…",
  "size_bytes": 5054234,
  "expires_at": "2026-04-24T11:00:00Z",
  "max_downloads": 1,
  "created_at": "2026-04-23T11:00:00Z"
}
Capture the password immediately. It appears only in this response. We store an Argon2id hash and discard the plaintext — there is no endpoint to retrieve it again. If the recipient loses it, use /reissue-password to invalidate the link and issue a replacement.

Download via curl

The download endpoint accepts the access password via HTTP Basic auth — the URL path is the document ID, the username is ignored, and the password is the one-time access password. This makes it trivial for recipients to retrieve the PDF from a terminal or CI pipeline.

GET /v2/documents/{id}/content
curl · download
# Option A — Basic auth (password only)
curl -u ":R4TA-9XPM-KQV7-B2LD-ZN8E" \
  -o q1-audit-report.pdf \
  https://secdl.portal42.cc/d/SDL-2026-0423-AC4F/content

# Option B — X-Access-Password header
curl -H "X-Access-Password: R4TA-9XPM-KQV7-B2LD-ZN8E" \
  -o q1-audit-report.pdf \
  https://secdl.portal42.cc/d/SDL-2026-0423-AC4F/content

# Verify the checksum
shasum -a 256 q1-audit-report.pdf
# e3b0c44298fc1c149afbf4c8996fb924…  q1-audit-report.pdf
Response is the raw PDF. Content-Type is application/pdf, Content-Disposition includes the original filename, and the SHA-256 is returned in the X-Checksum-Sha256 header so CI jobs can verify integrity without parsing JSON.

Revoke & reissue

POST /v2/documents/{id}/reissue-password

Invalidates the current password and issues a fresh one. Use this when the recipient has lost their password or when a password may have been exposed. The document itself and the download URL remain unchanged — only the password rotates.

curl · reissue
curl -X POST \
  -H "Authorization: Bearer $SECDL_API_KEY" \
  https://api.secdl.portal42.cc/v2/documents/SDL-2026-0423-AC4F/reissue-password

# Response
{
  "password": "7BNC-MX2E-4HPV-LKS9-DRQA",   // new one-time password
  "previous_invalidated_at": "2026-04-23T14:21:07Z"
}

Errors

CodeMeaningWhen
400invalid_requestMissing or malformed field — see error.field.
401invalid_passwordAccess password does not match. After 5 failures the link self-destructs.
403insufficient_scopeAPI key lacks permission on this document's organization.
404not_foundDocument ID unknown, or link was revoked.
410goneExpired or already consumed (max_downloads reached).
429rate_limitedSee Retry-After header.

Rate limits

Upload: 60 requests per minute per API key. Download (per document): 10 password attempts total before self-destruct, 2 retrievals per second after authentication.

secdl Secure Document Exchange · API v2 · Last updated 2026-04-23 · Back to download portal