Estimate exports

6 endpointówTylko po angielsku

List an estimate's hand-offs

get/estimates/{estimateId}/handoffsexperimentalWymagana sesja

Returns every recorded hand-off, newest createdAt first. Responds 403 when the caller is not a member of the estimate's workshop and 404 when no such estimate exists.

Parametry ścieżki

NazwaTypWymaganeOgraniczeniaOpis
estimateIdstringTak-Estimate id

Odpowiedzi

  • 200Success
    PoleTypWymaganeOgraniczeniaOpis
    handoffsarray of HandoffTak--
    Przykład
    {
      "handoffs": [
        {
          "id": "handoff-1",
          "kind": "pdf-shared",
          "locale": "pl",
          "preliminary": false,
          "tone": "friendly",
          "aiDrafted": false,
          "revisionNumber": 1,
          "createdAt": "2026-08-10T14:40:00.000Z",
          "createdByUid": "uid-1",
          "pdfExportId": "pdf-export-1"
        }
      ]
    }
  • 401Not authenticated

    Brak treści.

  • 403Forbidden

    Brak treści.

  • 404Not found

    Brak treści.

Przykładowe żądanie

curl -X GET 'https://mercastra.cloud/api/estimates/<estimateId>/handoffs' \
  -H 'Cookie: session=<session cookie>'

Record that an estimate was handed off to its recipient

post/estimates/{estimateId}/handoffsexperimentalWymagana sesja

Records that a hand-off happened; it does not send anything itself, the caller performs the copy, share or open action and reports it here afterward. None of kind, tone or aiDrafted is verified against anything that actually happened, they are trusted as given. The body is strict, an unknown field is a 400. When pdfExportId is given it must identify an existing pdf export on this estimate; if it does not, this also responds 400, but with an empty body, not the ValidationError JSON a schema violation sends - the two 400 causes are otherwise indistinguishable from the status code alone. Responds 403 when the caller is not a member of the estimate's workshop and 404 when no such estimate exists.

Parametry ścieżki

NazwaTypWymaganeOgraniczeniaOpis
estimateIdstringTak-Estimate id

Treść żądania

PoleTypWymaganeOgraniczeniaOpis
kindHandoffKindTak-How a crafter delivered an estimate to its recipient, one of these five values: message-copied, message-shared, pdf-shared, pdf-and-message-shared or email-opened. Caller-supplied and not verified against anything that actually happened, see the hand-off endpoint's own description.
localeDocumentLocaleTak-The language a generated estimate PDF or hand-off message is written in: pl (Polish) or en (English).
preliminarybooleanTak--
toneMessageToneTak-The tone of a hand-off message, formal or friendly. Recorded on every hand-off regardless of aiDrafted, not just ones whose text came from the AI draft endpoint.
aiDraftedbooleanTak--
pdfExportIdstringNieminLength: 1An existing pdf export to associate with this hand-off, when one was involved.
Przykład
{
  "kind": "pdf-shared",
  "locale": "pl",
  "preliminary": false,
  "tone": "friendly",
  "aiDrafted": false,
  "pdfExportId": "pdf-export-1"
}

Odpowiedzi

  • 201Created
    PoleTypWymaganeOgraniczeniaOpis
    idstringTak--
    kindHandoffKindTak-How a crafter delivered an estimate to its recipient, one of these five values: message-copied, message-shared, pdf-shared, pdf-and-message-shared or email-opened. Caller-supplied and not verified against anything that actually happened, see the hand-off endpoint's own description.
    localeDocumentLocaleTak-The language a generated estimate PDF or hand-off message is written in: pl (Polish) or en (English).
    preliminarybooleanTak--
    toneMessageToneTak-The tone of a hand-off message, formal or friendly. Recorded on every hand-off regardless of aiDrafted, not just ones whose text came from the AI draft endpoint.
    aiDraftedbooleanTak-Whether the delivered message text came from POST .../message-draft rather than being hand-written.
    revisionNumbernumberTak-The estimate's latest revision number at the time of hand-off.
    createdAtstringTakformat: "date-time"-
    createdByUidstringTak--
    pdfExportIdstringNie-The pdf export this hand-off refers to, when one was involved. Absent otherwise.
    Przykład
    {
      "id": "handoff-1",
      "kind": "pdf-shared",
      "locale": "pl",
      "preliminary": false,
      "tone": "friendly",
      "aiDrafted": false,
      "revisionNumber": 1,
      "createdAt": "2026-08-10T14:40:00.000Z",
      "createdByUid": "uid-1",
      "pdfExportId": "pdf-export-1"
    }
  • 400Either the body fails schema validation (ValidationError JSON) or pdfExportId does not identify a pdf export belonging to this estimate (empty body) - see this endpoint's description.

    Wspólna treść błędu walidacji, zobacz Błędy walidacji.

  • 401Not authenticated

    Brak treści.

  • 403Forbidden

    Brak treści.

  • 404Not found

    Brak treści.

Przykładowe żądanie

curl -X POST 'https://mercastra.cloud/api/estimates/<estimateId>/handoffs' \
  -H 'Cookie: session=<session cookie>' \
  -H 'X-CSRF-Token: <csrf-token cookie value>' \
  -H 'Content-Type: application/json' \
  -d '{"kind":"pdf-shared","locale":"pl","preliminary":false,"tone":"friendly","aiDrafted":false,"pdfExportId":"pdf-export-1"}'

List an estimate's PDF exports

get/estimates/{estimateId}/pdf-exportsexperimentalWymagana sesja

Returns every stored pdf export's metadata, newest generatedAt first. Responds 403 when the caller is not a member of the estimate's workshop and 404 when no such estimate exists.

Parametry ścieżki

NazwaTypWymaganeOgraniczeniaOpis
estimateIdstringTak-Estimate id

Odpowiedzi

  • 200Success
    PoleTypWymaganeOgraniczeniaOpis
    pdfExportsarray of PdfExportTak--
    Przykład
    {
      "pdfExports": [
        {
          "id": "pdf-export-1",
          "revisionNumber": 1,
          "toggles": {
            "breakdown": true,
            "showMarkup": true,
            "showDiscount": false,
            "showRecipient": true,
            "showBrandMark": true
          },
          "generatedAt": "2026-08-10T14:35:00.000Z",
          "createdByUid": "uid-1",
          "locale": "en",
          "preliminary": false
        }
      ]
    }
  • 401Not authenticated

    Brak treści.

  • 403Forbidden

    Brak treści.

  • 404Not found

    Brak treści.

Przykładowe żądanie

curl -X GET 'https://mercastra.cloud/api/estimates/<estimateId>/pdf-exports' \
  -H 'Cookie: session=<session cookie>'

Generate a PDF export of an estimate

post/estimates/{estimateId}/pdf-exportsexperimentalWymagana sesja

Renders the estimate's current content (not a specific revision) into a PDF, stores it as a file scoped to the estimate and records its metadata; every toggle and locale defaults server-side when omitted, see PdfExportOptions and DocumentLocale. The body is strict, an unknown field is a 400. Responds 201 with the new PdfExport and a Location header pointing to GET .../pdf-exports/{pdfExportId}. Responds 403 when the caller is not a member of the estimate's workshop and 404 when no such estimate exists. Responds 413 with an empty body when generating this PDF would exceed the workshop's plan file storage quota.

Parametry ścieżki

NazwaTypWymaganeOgraniczeniaOpis
estimateIdstringTak-Estimate id

Treść żądania

PoleTypWymaganeOgraniczeniaOpis
breakdownbooleanNiedefault: trueInclude the itemized line-item breakdown table.
showMarkupbooleanNiedefault: falseShow the markup percentage and amount.
showDiscountbooleanNiedefault: falseShow the discount percentage and amount.
showRecipientbooleanNiedefault: trueShow the recipient's name.
showBrandMarkbooleanNiedefault: trueShow Mercastra's brand mark. A workshop whose plan cannot disable it (see entitlements) has this forced back to true server-side regardless of what is sent.
localeDocumentLocaleNie-Defaults to Polish.
preliminarybooleanNiedefault: falseMarks the PDF as a preliminary estimate, changing its disclaimer text.
Przykład
{
  "locale": "en",
  "showMarkup": true
}

Odpowiedzi

  • 201Created
    PoleTypWymaganeOgraniczeniaOpis
    idstringTak--
    revisionNumbernumberTak-The estimate's latest revision number at the time of export.
    togglesPdfExportOptionsTak-The visual toggles for a generated estimate PDF, each defaulting server-side when omitted.
    generatedAtstringTakformat: "date-time"-
    createdByUidstringTak--
    localeDocumentLocaleNie-Absent only on a pdf export generated before locale was tracked.
    preliminarybooleanNie-Absent only on a pdf export generated before preliminary was tracked.
    Przykład
    {
      "id": "pdf-export-1",
      "revisionNumber": 1,
      "toggles": {
        "breakdown": true,
        "showMarkup": true,
        "showDiscount": false,
        "showRecipient": true,
        "showBrandMark": true
      },
      "generatedAt": "2026-08-10T14:35:00.000Z",
      "createdByUid": "uid-1",
      "locale": "en",
      "preliminary": false
    }
  • 400The request body does not match the schema

    Wspólna treść błędu walidacji, zobacz Błędy walidacji.

  • 401Not authenticated

    Brak treści.

  • 403Forbidden

    Brak treści.

  • 404Not found

    Brak treści.

  • 413Generating this PDF would exceed the workshop's plan file storage quota

    Brak treści.

Przykładowe żądanie

curl -X POST 'https://mercastra.cloud/api/estimates/<estimateId>/pdf-exports' \
  -H 'Cookie: session=<session cookie>' \
  -H 'X-CSRF-Token: <csrf-token cookie value>' \
  -H 'Content-Type: application/json' \
  -d '{"locale":"en","showMarkup":true}'

Download a PDF export's bytes

get/estimates/{estimateId}/pdf-exports/{pdfExportId}experimentalWymagana sesja

Streams the stored PDF with Content-Disposition: attachment and a filename derived from the export's locale (estimate-<id>.pdf for en, wycena-<id>.pdf for pl). Responds 403 when the caller is not a member of the estimate's workshop and 404 both when no such estimate or pdf export exists and when the pdf export id belongs to a different estimate - the three cases are indistinguishable in the response.

Parametry ścieżki

NazwaTypWymaganeOgraniczeniaOpis
estimateIdstringTak-Estimate id
pdfExportIdstringTak-Pdf export id

Odpowiedzi

  • 200Success

    Brak treści.

  • 401Not authenticated

    Brak treści.

  • 403Forbidden

    Brak treści.

  • 404Not found

    Brak treści.

Przykładowe żądanie

curl -X GET 'https://mercastra.cloud/api/estimates/<estimateId>/pdf-exports/<pdfExportId>' \
  -H 'Cookie: session=<session cookie>'

Delete a PDF export

delete/estimates/{estimateId}/pdf-exports/{pdfExportId}experimentalWymagana sesja

Permanently deletes the pdf export's metadata record and its stored bytes, freeing the workshop's file storage quota it used. Responds 200 with an empty body on success, not 204 - a hand-maintained doc has previously claimed 204, that was wrong, the route calls res.status(200).send(). Responds 403 when the caller is not a member of the estimate's workshop and 404 both when no such estimate or pdf export exists and when the pdf export id belongs to a different estimate - the three cases are indistinguishable in the response.

Parametry ścieżki

NazwaTypWymaganeOgraniczeniaOpis
estimateIdstringTak-Estimate id
pdfExportIdstringTak-Pdf export id

Odpowiedzi

  • 200Success

    Brak treści.

  • 401Not authenticated

    Brak treści.

  • 403Forbidden

    Brak treści.

  • 404Not found

    Brak treści.

Przykładowe żądanie

curl -X DELETE 'https://mercastra.cloud/api/estimates/<estimateId>/pdf-exports/<pdfExportId>' \
  -H 'Cookie: session=<session cookie>' \
  -H 'X-CSRF-Token: <csrf-token cookie value>'