Skip to main content

Upload Document

Upload a document (PDF, PowerPoint, or Word file) and publish it as a LinkedIn document post.

Endpoint​

POST https://api.indreelforge.com/api/upload_document

Authentication​

Authorization: Apikey YOUR_API_KEY

Platform Support​

Document posts are currently supported on LinkedIn only. The platform is fixed to linkedin — you do not pass a platform[] parameter for this endpoint.

info

Your LinkedIn account must be connected in the profile you specify via the user field. LinkedIn document posts are available on all paid plans.

Parameters​

Required​

ParameterTypeDescription
documentfileDocument file to upload. Accepted formats: PDF, PPT, PPTX, DOC, DOCX. Max 100 MB.
userstringProfile name (case-sensitive) to post from.

Optional — General​

ParameterTypeDescription
titlestringTitle of the document post. Defaults to the original filename if omitted.
descriptionstringBody text / caption for the LinkedIn post.
scheduledatetimeISO 8601 timestamp to schedule the post (e.g. 2026-06-15T09:00:00Z). Must be a future time. Requires a paid plan with scheduling enabled.
schedule_atdatetimeAlias for schedule. Either field is accepted.
timezonestringIANA timezone string for display purposes (e.g. America/New_York).
request_idstringYour own idempotency / tracking ID. Returned in the response.

LinkedIn-Specific​

ParameterTypeDescription
visibilitystringPost audience. PUBLIC (default) or CONNECTIONS.
target_linkedin_page_idstringPost to a LinkedIn Company Page instead of your personal profile. Pass the page URN or numeric ID.

Idempotency​

Pass an Idempotency-Key request header with a unique string to safely retry the same request without creating duplicate posts. If the key has already been processed, the original upload record is returned immediately.

Supported File Types​

FormatExtension(s)Notes
PDF.pdfVerified via %PDF magic bytes
PowerPoint (legacy).pptVerified via OLE2 Compound File magic bytes
PowerPoint (modern).pptxVerified via ZIP/OOXML magic bytes
Word (legacy).docVerified via OLE2 Compound File magic bytes
Word (modern).docxVerified via ZIP/OOXML magic bytes

All uploads are verified against their file magic bytes after multer writes the file to disk. Files whose content does not match the declared extension are rejected with INVALID_FILE_CONTENT.

note

This endpoint accepts multipart file uploads only. There is no remote URL support for document uploads — the file must be sent as a form field named document.

File Size Limit​

LinkedIn enforces a 100 MB maximum for document uploads. Requests exceeding this limit are rejected with HTTP 413 before the file reaches LinkedIn.

Plan Gating​

  • Document uploads count against your monthly upload quota. Free plan users receive 10 uploads/month.
  • Scheduling (schedule / schedule_at) requires a paid plan (Basic or above). Free-plan requests with a schedule value are rejected with HTTP 403 and SCHEDULING_NOT_AVAILABLE.

Examples​

cURL​

curl \
-H 'Authorization: Apikey YOUR_API_KEY' \
-F 'document=@/path/to/presentation.pdf' \
-F 'user=my-brand' \
-F 'title=Q2 2026 Results' \
-F 'description=Our highlights from Q2 — swipe to read the full report.' \
-F 'visibility=PUBLIC' \
-X POST https://api.indreelforge.com/api/upload_document

Schedule for later​

curl \
-H 'Authorization: Apikey YOUR_API_KEY' \
-F 'document=@/path/to/deck.pptx' \
-F 'user=my-brand' \
-F 'title=Product Roadmap' \
-F 'schedule=2026-06-15T09:00:00Z' \
-X POST https://api.indreelforge.com/api/upload_document

Post to a LinkedIn Company Page​

curl \
-H 'Authorization: Apikey YOUR_API_KEY' \
-F 'document=@/path/to/report.pdf' \
-F 'user=my-brand' \
-F 'title=Annual Report 2025' \
-F 'target_linkedin_page_id=123456789' \
-X POST https://api.indreelforge.com/api/upload_document

JavaScript​

const form = new FormData();
form.append('document', fs.createReadStream('/path/to/presentation.pdf'));
form.append('user', 'my-brand');
form.append('title', 'Q2 2026 Results');
form.append('description', 'Our highlights from Q2.');
form.append('visibility', 'PUBLIC');

const response = await fetch('https://api.indreelforge.com/api/upload_document', {
method: 'POST',
headers: { 'Authorization': 'Apikey YOUR_API_KEY' },
body: form,
});

const data = await response.json();
console.log(data);

Python​

import requests

files = {'document': open('/path/to/presentation.pdf', 'rb')}
data = {
'user': 'my-brand',
'title': 'Q2 2026 Results',
'description': 'Our highlights from Q2.',
'visibility': 'PUBLIC',
}
headers = {'Authorization': 'Apikey YOUR_API_KEY'}

response = requests.post(
'https://api.indreelforge.com/api/upload_document',
files=files,
data=data,
headers=headers,
)
print(response.json())

Response​

HTTP 201 — document queued for immediate posting:

{
"success": true,
"message": "Document upload queued successfully",
"request_id": "req_abc123",
"data": {
"upload_id": "upl_abc123",
"platforms": {
"linkedin": { "status": "queued" }
},
"total_platforms": 1
}
}

HTTP 202 — document scheduled for future posting:

{
"success": true,
"message": "Document upload scheduled",
"request_id": "req_abc123",
"data": {
"upload_id": "upl_abc123",
"platforms": {
"linkedin": { "status": "queued" }
},
"total_platforms": 1
}
}

After the job runs, poll GET /api/upload/{id}/status to check the final publish status and retrieve the LinkedIn post URL.

Error Responses​

StatusError CodeDescription
400INVALID_FILE_CONTENTFile magic bytes do not match the declared extension, or a non-document file was submitted.
400PLATFORM_NOT_CONNECTEDLinkedIn is not connected for the specified profile.
400INVALID_SCHEDULEschedule value could not be parsed as an ISO 8601 timestamp.
400SCHEDULE_IN_PASTschedule resolves to a time in the past.
401—Missing or invalid API key.
403UPLOAD_LIMIT_REACHEDMonthly upload quota exhausted. Upgrade your plan or wait for reset.
403SCHEDULING_NOT_AVAILABLEScheduling requires a paid plan.
404PROFILE_NOT_FOUNDNo profile matching the user field was found for your account.
413FILE_TOO_LARGE_FOR_PLATFORMDocument exceeds LinkedIn's 100 MB limit.
429PLATFORM_RATE_LIMITLinkedIn's daily posting limit has been reached (150 posts/day).
500—Internal server error.
502B2_UPLOAD_FAILEDFile was received but could not be stored in object storage. Retry the request.
503STORAGE_NOT_CONFIGUREDObject storage is not configured on the server.