POST /api/v2/files endpoint accepts a multipart/form-data upload and returns a CDN URL you can reference from any other v2 resource that accepts file URLs (changelog image_url, help center article body, thread message attachments, etc.).
This is the only v2 endpoint that does not accept JSON - multipart is required because we stream the upload straight to storage without buffering the whole file in memory.
Authentication
Standard v2 bearer auth. The key must have thefiles:write scope.
Limits
| Limit | Value |
|---|---|
| Max file size | 10 MB per request |
| Per-key burst | 30 uploads / minute |
| Per-workspace daily | 500 uploads / day |
60/min/key) also applies, in addition to the upload-specific budget above.
Allowed content types
Uploads are validated byContent-Type. Anything outside this list is rejected with 400 validation_failed. image/svg+xml, text/html, and application/octet-stream are deliberately excluded to prevent hosting hostile content.
Images
image/pngimage/jpegimage/gifimage/webp
application/pdfapplication/msword(.doc)application/vnd.openxmlformats-officedocument.wordprocessingml.document(.docx)application/vnd.ms-excel(.xls)application/vnd.openxmlformats-officedocument.spreadsheetml.sheet(.xlsx)application/vnd.ms-powerpoint(.ppt)application/vnd.openxmlformats-officedocument.presentationml.presentation(.pptx)text/csvtext/plain
Request
POST https://productlane.com/api/v2/files
Body: multipart/form-data with a single field named file.
| Field | Type | Required | Description |
|---|---|---|---|
file | binary | yes | The file to upload. Must match one of the allowed content types and be ≤ 10 MB. |
Response
200 OK
| Field | Description |
|---|---|
file_url | Public CDN URL of the uploaded file. Pass this to any endpoint that accepts a file URL. |
content_type | Normalized lowercase content type the server stored. |
size | File size in bytes after upload. |
original_file_name | Filename you uploaded with, if any. null if the multipart part had no filename. |
Using the URL
The most common destinations:- Changelog cover image - pass
file_urlasimage_urlonPOST /changelogsorPATCH /changelogs/{id}. - Help center article body - embed the URL inline in the article HTML you send to
POST /docs/articles(<img src="...">). - Thread message attachments - pass the URL as part of the
attachmentsarray onPOST /threads/{thread_id}/messages.
Errors
The standard v2 error envelope is returned for every non-2xx response.| Status | Code | When |
|---|---|---|
| 400 | validation_failed | Missing file field, content type not allowed, or other validation. |
| 401 | unauthenticated | Missing or invalid bearer token. |
| 403 | scope_required | Key does not have the files:write scope. |
| 410 | unsupported_key_version | v1 key (pl_*) hit this endpoint. Mint a v2 key. |
| 413 | validation_failed | File exceeds the 10 MB limit. |
| 429 | rate_limited | Per-key or per-workspace upload budget exhausted. |
X-Request-Id header. Include it when contacting support.
Notes
- No deletion endpoint. Uploaded files persist; we don’t currently expose a way to delete them. If you need a file gone (e.g. credential leak in an upload), revoke the key and contact support.
- CDN is public. Don’t upload anything that should be private - the URL is unguessable but not auth-gated.
- Retries are safe but produce a new URL. This endpoint has no idempotency key; retrying an upload uploads the same content twice and returns two different URLs.