https://www.helprange.com/api/v2/offers/{offer_id}/filesAdds documents from folders you can open (up to 50). Answers with the offer.
Plans: Max, Unlimited, Deal Room Pass, trial. Auth: Authorization: Bearer hr_live_… (team key), X-API-Key, Authorization: Api-Key <key> or an OAuth Bearer token. Scope: links:write. Operation id: addOfferFiles
| Name | In | Type | Description |
|---|---|---|---|
offer_id required | path | integer | Offer id (from List offers). (min 1) |
Content types: application/json, application/x-www-form-urlencoded.
| Field | Type | Description |
|---|---|---|
file_ids required | array of integer | Document ids. |
curl -X POST https://www.helprange.com/api/v2/offers/31/files \
-H "X-API-Key: $HELPRANGE_API_KEY" \
-H 'Content-Type: application/json' \
--data-binary '{"file_ids": [252]}'
const res = await fetch('https://www.helprange.com/api/v2/offers/31/files', {
method: 'POST',
headers: {'X-API-Key': process.env.HELPRANGE_API_KEY, 'Content-Type': 'application/json'},
body: JSON.stringify({
"file_ids": [
252
]
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.error || data.message || data.reason}`);
console.log(data);
import os
import requests
r = requests.post(
'https://www.helprange.com/api/v2/offers/31/files',
headers={'X-API-Key': os.environ['HELPRANGE_API_KEY']},
json={
"file_ids": [252],
},
timeout=60,
)
r.raise_for_status()
print(r.json())
The samples read the key from the HELPRANGE_API_KEY environment variable.
| Status | Description |
|---|---|
200 | OK |
400 | Invalid input – the message says which parameter. |
401 | Missing or invalid API key / OAuth token. Team keys: code invalid_key, key_revoked, key_expired or key_owner_removed. |
402 | Your plan does not include the REST API (or this feature). |
403 | The team API key lacks the scope this endpoint needs. |
404 | Not found – or not yours (the API never says which). |
405 | Wrong HTTP method for this endpoint. |
429 | A usage limit was reached – wait Retry-After seconds. |
{
"id": 31,
"title": "Fit-out Q1",
"status": "active",
"expired": false,
"client": {
"first_name": "Anna",
"last_name": "Nowak",
"company": "Acme",
"email": "anna@acme.com"
},
"kind": "files",
"url": "https://www.helprange.com/o/Xk2pQ9/",
"document_views": 4,
"page_visits": 2,
"last_viewed_at": "2026-11-11T09:12:00+00:00",
"sent_at": null,
"created_at": "2026-11-11T08:00:00+00:00",
"updated_at": "2026-11-11T08:00:00+00:00",
"stored_status": "active",
"public_url": "https://www.helprange.com/o/Xk2pQ9/",
"panel_url": "https://www.helprange.com/user/offers/31/",
"message": "Hi Anna, here is our proposal.",
"price_summary": "from 2,400 EUR",
"buttons": {
"accept": {
"shown": true,
"label": ""
},
"contact": {
"shown": true,
"label": ""
},
"decline": {
"shown": true,
"label": ""
}
},
"protection": {
"require_email_verification": true,
"access": "domain",
"allowed_emails": "anna@acme.com @acme.com",
"allow_download": false,
"watermark": false,
"passcode": true,
"screenshot_protection": false,
"one_viewer_at_a_time": false,
"expires_on": "2026-12-31"
},
"open_directly": false,
"layout": "classic",
"theme": "light",
"base_folder": null,
"own_folder": {
"id": 77,
"name": "Offer - Fit-out Q1"
},
"files": [
{
"id": 250,
"name": "proposal.pdf",
"folder_id": 77,
"source": "own_folder",
"view_url": "https://www.helprange.com/view/5b0c.../proposal.pdf",
"views": 3
}
],
"people": 1,
"engagement": 82,
"responses_count": 1,
"responses": [
{
"kind": "declined the offer",
"type": "decline",
"offer_id": 31,
"email": "anna@acme.com",
"email_verified": true,
"offer": "Fit-out Q1",
"comment": "Too expensive",
"document_id": null,
"engagement": 64,
"country": "PL",
"at": "2026-11-11T10:00:00+00:00"
}
],
"sent_to": null,
"created_by": "ann@acme.com",
"legacy_url": null,
"send_by_email": "HelpRange does not e-mail offers through the API or MCP. Send the offer link (url) yourself, or use \"Send by e-mail\" on the offer page in HelpRange."
}
Uses your real account. The request goes from your browser straight to www.helprange.com with your API key and acts as you – this POST changes data. The key stays in this page (in this tab's session storage only if you tick the box), is never put in a URL and is not sent to analytics. Do not paste a key on a shared computer.