curl --request POST \
--url https://api.instaview.sk/contacts/{id}/documents/uploads \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"fileName": "benefits-and-perks.pdf",
"mimeType": "application/pdf",
"sizeBytes": 482133,
"title": "Benefits and perks"
}
'import requests
url = "https://api.instaview.sk/contacts/{id}/documents/uploads"
payload = {
"fileName": "benefits-and-perks.pdf",
"mimeType": "application/pdf",
"sizeBytes": 482133,
"title": "Benefits and perks"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
fileName: 'benefits-and-perks.pdf',
mimeType: 'application/pdf',
sizeBytes: 482133,
title: 'Benefits and perks'
})
};
fetch('https://api.instaview.sk/contacts/{id}/documents/uploads', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.instaview.sk/contacts/{id}/documents/uploads",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'fileName' => 'benefits-and-perks.pdf',
'mimeType' => 'application/pdf',
'sizeBytes' => 482133,
'title' => 'Benefits and perks'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.instaview.sk/contacts/{id}/documents/uploads"
payload := strings.NewReader("{\n \"fileName\": \"benefits-and-perks.pdf\",\n \"mimeType\": \"application/pdf\",\n \"sizeBytes\": 482133,\n \"title\": \"Benefits and perks\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.instaview.sk/contacts/{id}/documents/uploads")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"fileName\": \"benefits-and-perks.pdf\",\n \"mimeType\": \"application/pdf\",\n \"sizeBytes\": 482133,\n \"title\": \"Benefits and perks\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.instaview.sk/contacts/{id}/documents/uploads")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"fileName\": \"benefits-and-perks.pdf\",\n \"mimeType\": \"application/pdf\",\n \"sizeBytes\": 482133,\n \"title\": \"Benefits and perks\"\n}"
response = http.request(request)
puts response.read_body{
"document": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"title": "Benefits and perks",
"status": "READY",
"isActive": true,
"source": "UPLOAD",
"createdAt": "2026-08-08T10:15:00.000Z",
"fileName": "benefits-and-perks.pdf",
"mimeType": "application/pdf",
"sizeBytes": 482133
},
"uploadUrl": "https://instaview-agent-knowledge-production.s3.eu-central-1.amazonaws.com/agent-knowledge/...",
"uploadMethod": "PUT",
"contentType": "application/pdf",
"expiresAt": "2026-08-08T10:30:00.000Z",
"maxBytes": 20971520
}Start Contact Document Upload
Reserves a document slot on the contact — and the declared bytes against your company’s contact-document storage — and returns a presigned URL to upload the file to. The file never passes through this API.
POSTthis endpoint with the file’s name, MIME type and size.PUTthe raw file bytes to the returneduploadUrl, sendingContent-Typeexactly as returned incontentType. Do not send your API key with this request — the URL carries its own authorisation.POST /contacts/{id}/documents/{documentId}/completeto confirm the upload.
The document stays PENDING, and is never used on a call, until step 3 succeeds. Uploads that are never completed are cleaned up automatically after 24 hours and release both the slot and the bytes they reserved.
A contact holds at most 5 uploaded documents. The company’s total contact-document storage is capped by its plan; a request that would exceed it is refused with a 400 naming the bytes in use, the ceiling and the size requested.
This endpoint has a lower rate limit than the rest of the API.
curl --request POST \
--url https://api.instaview.sk/contacts/{id}/documents/uploads \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"fileName": "benefits-and-perks.pdf",
"mimeType": "application/pdf",
"sizeBytes": 482133,
"title": "Benefits and perks"
}
'import requests
url = "https://api.instaview.sk/contacts/{id}/documents/uploads"
payload = {
"fileName": "benefits-and-perks.pdf",
"mimeType": "application/pdf",
"sizeBytes": 482133,
"title": "Benefits and perks"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
fileName: 'benefits-and-perks.pdf',
mimeType: 'application/pdf',
sizeBytes: 482133,
title: 'Benefits and perks'
})
};
fetch('https://api.instaview.sk/contacts/{id}/documents/uploads', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.instaview.sk/contacts/{id}/documents/uploads",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'fileName' => 'benefits-and-perks.pdf',
'mimeType' => 'application/pdf',
'sizeBytes' => 482133,
'title' => 'Benefits and perks'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.instaview.sk/contacts/{id}/documents/uploads"
payload := strings.NewReader("{\n \"fileName\": \"benefits-and-perks.pdf\",\n \"mimeType\": \"application/pdf\",\n \"sizeBytes\": 482133,\n \"title\": \"Benefits and perks\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.instaview.sk/contacts/{id}/documents/uploads")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"fileName\": \"benefits-and-perks.pdf\",\n \"mimeType\": \"application/pdf\",\n \"sizeBytes\": 482133,\n \"title\": \"Benefits and perks\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.instaview.sk/contacts/{id}/documents/uploads")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"fileName\": \"benefits-and-perks.pdf\",\n \"mimeType\": \"application/pdf\",\n \"sizeBytes\": 482133,\n \"title\": \"Benefits and perks\"\n}"
response = http.request(request)
puts response.read_body{
"document": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"title": "Benefits and perks",
"status": "READY",
"isActive": true,
"source": "UPLOAD",
"createdAt": "2026-08-08T10:15:00.000Z",
"fileName": "benefits-and-perks.pdf",
"mimeType": "application/pdf",
"sizeBytes": 482133
},
"uploadUrl": "https://instaview-agent-knowledge-production.s3.eu-central-1.amazonaws.com/agent-knowledge/...",
"uploadMethod": "PUT",
"contentType": "application/pdf",
"expiresAt": "2026-08-08T10:30:00.000Z",
"maxBytes": 20971520
}Overview
The same three-step flow as an agent knowledge upload, because the file bytes go straight to storage and never pass through this API.Reserve a slot
POST /contacts/{id}/documents/uploads with the file’s name, MIME type and size. You get back a documentId and an uploadUrl.sizeBytes must be the file’s exact byte count. It is signed into the upload URL, and it is
also what is reserved against your company’s contact-document storage — so a larger file is
refused at completion, not quietly admitted.Upload the file
PUT the raw file bytes to uploadUrl, sending Content-Type exactly as returned in contentType.Complete the upload
POST /contacts/{id}/documents/{documentId}/complete. The stored file is verified, and only then does the document become usable on calls.Example
# 1. Reserve a slot
curl -X POST https://api.instaview.sk/contacts/$CONTACT_ID/documents/uploads \
-H "Authorization: Bearer $INSTAVIEW_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fileName": "cover-letter.pdf",
"mimeType": "application/pdf",
"sizeBytes": 482133,
"title": "Cover letter"
}'
# 2. Upload the bytes (no API key on this request)
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: application/pdf" \
--data-binary @cover-letter.pdf
# 3. Confirm
curl -X POST https://api.instaview.sk/contacts/$CONTACT_ID/documents/$DOCUMENT_ID/complete \
-H "Authorization: Bearer $INSTAVIEW_API_KEY"
Supported File Types
PDF, DOC, DOCX, TXT, MD, CSV, TSV, JSON, XML and YAML — the same set as agent knowledge.Limits
| Limit | Value |
|---|---|
| Maximum file size | 20 MiB (20,971,520 bytes) |
| Uploaded documents per contact | 5 (the CV document does not count) |
| Contact-document storage per company | Plan-tiered; the 400 names the figures when exceeded |
| Upload URL validity | 15 minutes |
| Unfinished uploads reclaimed after | 24 hours |
DELETE the document.400 of the form:
Contact document storage limit reached for this company: 248MB of 250MB in use, and this file needs 3MB more.
Delete contact documents or upgrade the plan.
Rate Limiting
Shares the agent knowledge upload limit: 6 requests per minute and 60 per hour per API key for this endpoint, with completion limited separately and more generously. A429 carries a Retry-After header.
Error Scenarios
- 400 Bad Request: Unsupported file type, a size over 20 MB, the contact already holds 5 documents, or the company is at its storage limit
- 404 Not Found: No contact with that id belongs to your API key’s company
- 429 Too Many Requests: Upload rate limit exceeded — wait for
Retry-Afterseconds
Related Resources
Authorizations
API key for authentication using Bearer scheme
Path Parameters
Contact the document belongs to.
Query Parameters
Required for ATS API keys to specify which company to access. Ignored for standard company API keys.
Body
Name of the file being uploaded, including its extension.
255"benefits-and-perks.pdf"
MIME type of the file. The returned upload URL is signed for this exact type, so the PUT must send it back as its Content-Type header verbatim.
application/pdf, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, text/plain, text/markdown, text/csv, text/tab-separated-values, application/json, application/xml, text/xml, application/yaml, text/yaml "application/pdf"
Exact size of the file in bytes. This is binding, not an estimate: it is signed into the upload URL, so the PUT must send precisely this many bytes and storage rejects anything else with a 403. Send the real byte count of the file you are about to upload; most HTTP clients set Content-Length for you from the body. Checked again against the stored object at completion.
1 <= x <= 20971520482133
Human-readable label for the document. Defaults to fileName.
255"Benefits and perks"
Response
Slot and bytes reserved, upload URL issued
The reserved document, in PENDING state until the upload is completed.
Show child attributes
Show child attributes
Presigned storage URL to PUT the file to. Carries its own authorisation — do not send your API key with it.
"https://instaview-agent-knowledge-production.s3.eu-central-1.amazonaws.com/agent-knowledge/..."
HTTP method the upload URL expects.
PUT "PUT"
The Content-Type header the PUT must send. It is part of the URL's signature, so any other value is rejected by storage.
"application/pdf"
When the upload URL stops working. The document slot outlives it — request a new upload if this expires.
"2026-08-08T10:30:00.000Z"
Maximum bytes the stored object may have. A larger file is rejected at completion and deleted.
20971520