POST

Update an offer (POST)

https://www.helprange.com/api/v2/offers/{offer_id}

Changes only the fields you send. The offer's links follow at once (protection, expiry, status). POST does the same as PATCH, for tools that cannot send PATCH. The API never e-mails the client: send the returned url yourself.

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: updateOfferPost

Parameters

NameInTypeDescription
offer_id requiredpathintegerOffer id (from List offers). (min 1)

Request body

Content types: application/json, application/x-www-form-urlencoded.

FieldTypeDescription
titlestringWhat the client sees as the title. Create: default the folder's / first document's name.
client_first_namestring
client_last_namestring
client_companystring
client_emailstringThe client's e-mail – never e-mailed by the API.
messagestringMessage on the offer page. (max length 2000)
price_summarystringOne line, e.g. "3 packages, from 2,400 EUR".
show_acceptboolean"Accept offer" button (default on).
accept_labelstring
show_contactboolean"Request contact" button (default on).
contact_labelstring
show_declineboolean"Decline" button with an optional reason (default off).
decline_labelstring
require_email_verificationbooleanThe client verifies their e-mail with a one-time code (default on).
access"any" | "email" | "domain"With e-mail verification: anyone, only client_email, or client_email and colleagues at the same domain.
allow_downloadboolean
watermarkboolean
expires_onstringLast day, YYYY-MM-DD ("" removes it).
passcodestringAsked before the offer opens ("" removes it).
screenshot_protectionbooleanPro and higher (else 402).
one_viewer_at_a_timeboolean
open_directlybooleanOne-file offers: open the document directly instead of the offer page.
layout"classic" | "split" | "cover" | "minimal"
status"active" | "draft" | "accepted" | "declined" | "closed"active also reopens an accepted, declined or archived offer; closed = archived.

Example request

curl -X POST https://www.helprange.com/api/v2/offers/31 \
  -H "X-API-Key: $HELPRANGE_API_KEY" \
  -H 'Content-Type: application/json' \
  --data-binary '{"status": "active", "expires_on": "2027-01-31", "one_viewer_at_a_time": true}'

The samples read the key from the HELPRANGE_API_KEY environment variable.

Responses

StatusDescription
200OK
400Invalid input – the message says which parameter.
401Missing or invalid API key / OAuth token. Team keys: code invalid_key, key_revoked, key_expired or key_owner_removed.
402Your plan does not include the REST API (or this feature).
403The team API key lacks the scope this endpoint needs.
404Not found – or not yours (the API never says which).
405Wrong HTTP method for this endpoint.
429A usage limit was reached – wait Retry-After seconds.
Example response · 200
{
  "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."
}

Try it

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 and may e-mail people. 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.