Quotes
GET /v1/quotes
Section titled “GET /v1/quotes”| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
status | query | string | No | draft | sent | accepted | declined | expired | converted |
customerId | query | string | No | Filter by customer |
limit | query | integer | No | Page size, 1-200 (default 50) |
cursor | query | string | No | Opaque cursor from meta.nextCursor |
curl https://api.rieckflow.com/v1/quotes \ -H "Authorization: Bearer $RIECK_API_KEY"const svar = await rieck.request("GET", "/v1/quotes");{ "data": [ {} ], "meta": { "nextCursor": null }}expired is derived: a sent quote whose validUntil has passed lists as expired even before the database has recorded it.application/jsonPossible errors 5
| HTTP | Code | Meaning |
|---|---|---|
| 400 | invalid_cursor | The cursor is malformed, expired or belongs to another list shape. |
| 401 | invalid_api_key | The API key is missing, invalid, expired or revoked. |
| 403 | api_not_included | The organisation’s plan does not include API access. |
| 403 | insufficient_scope | The key does not have the required scope. |
| 429 | rate_limited | The organisation’s rate budget is exhausted. |
POST /v1/quotes
Section titled “POST /v1/quotes”Creates a DRAFT in the quote numbering series. signatureMethod decides how the customer accepts: none (one click), simple (drawn signature) or mitid. With a signature method, acceptance can only come from the customer — never from an API call.
Request body fields 21
| Field | Type | Required | Description |
|---|---|---|---|
customerId | string | Yes | The customer this resource belongs to. |
validUntil | string | Yes | Field in the request payload. |
heading | string | No | Custom document heading. |
customerReference | string | No | The customer’s reference printed on the invoice. |
senderReference | string | No | Your reference printed on the invoice. |
message | string | No | Free-text message printed in the document footer. |
signatureMethod | string | No | Field in the request payload. |
departmentCode | string | No | Field in the request payload. |
lines | object[] | Yes | Invoice or subscription line items. |
lines[].itemNumber | string | No | Your own item number printed on the invoice. |
lines[].description | string | Yes | Human-readable description. |
lines[].descriptionDetails | string | No | Optional detail printed below the line description. |
lines[].quantity | number | Yes | Positive quantity for this line. |
lines[].unitPriceOere | integer | Yes | Unit price in integer øre. |
lines[].vatRateBps | integer | No | VAT rate in basis points. 2500 means 25%. |
lines[].vatExemptionReason | string | No | Required legal reason when the VAT rate is zero. |
lines[].discount | object | No | Optional line-level percentage or amount discount. |
lines[].discount.type | string | Yes | Resource-specific type. |
lines[].discount.value | integer | Yes | Field in the request payload. |
lines[].accountId | string | No | Field in the request payload. |
lines[].unit | string | No | Field in the request payload. |
curl -X POST https://api.rieckflow.com/v1/quotes \ -H "Authorization: Bearer $RIECK_API_KEY" \ -H "Idempotency-Key: order-2041" \ -H "Content-Type: application/json" \ -d '{ "customerId": "9b2f1c1e-…", "validUntil": "…", "lines": [ { "description": "Consulting", "quantity": 1, "unitPriceOere": 125000, "vatRateBps": 2500 } ], "customerReference": "crm-9001", "senderReference": "crm-9001" }'const svar = await rieck.request("POST", "/v1/quotes", { body: { "customerId": "9b2f1c1e-…", "validUntil": "…", "lines": [ { "description": "Consulting", "quantity": 1, "unitPriceOere": 125000, "vatRateBps": 2500 } ], "customerReference": "crm-9001", "senderReference": "crm-9001" },});{ "data": {}}Possible errors 9
| HTTP | Code | Meaning |
|---|---|---|
| 400 | invalid_idempotency_key | Idempotency-Key is missing or malformed. |
| 400 | invalid_request | The request body or parameter failed validation. |
| 401 | invalid_api_key | The API key is missing, invalid, expired or revoked. |
| 403 | api_not_included | The organisation’s plan does not include API access. |
| 403 | insufficient_scope | The key does not have the required scope. |
| 409 | idempotency_conflict | The same key was used with a different request. |
| 409 | idempotency_in_progress | The same operation is currently being processed. Retry later. |
| 413 | payload_too_large | The JSON or uploaded file exceeds this endpoint’s size limit. |
| 429 | rate_limited | The organisation’s rate budget is exhausted. |
Request body — fuldt JSON Schema
{ "type": "object", "properties": { "customerId": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "validUntil": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" }, "heading": { "anyOf": [ { "type": "string", "minLength": 1, "maxLength": 60 }, { "type": "null" } ] }, "customerReference": { "anyOf": [ { "type": "string", "maxLength": 140 }, { "type": "null" } ] }, "senderReference": { "anyOf": [ { "type": "string", "maxLength": 140 }, { "type": "null" } ] }, "message": { "anyOf": [ { "type": "string", "maxLength": 2000 }, { "type": "null" } ] }, "signatureMethod": { "default": "none", "type": "string", "enum": [ "none", "simple", "mitid" ] }, "departmentCode": { "anyOf": [ { "type": "string", "pattern": "^\\d{1,2}$" }, { "type": "null" } ] }, "lines": { "minItems": 1, "maxItems": 100, "type": "array", "items": { "type": "object", "properties": { "itemNumber": { "type": "string", "minLength": 1, "maxLength": 60 }, "description": { "type": "string", "minLength": 1, "maxLength": 500 }, "descriptionDetails": { "type": "string", "maxLength": 500 }, "quantity": { "type": "number", "exclusiveMinimum": 0, "maximum": 999999 }, "unitPriceOere": { "type": "integer", "minimum": 0, "maximum": 100000000000 }, "vatRateBps": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "vatExemptionReason": { "anyOf": [ { "type": "string", "enum": [ "ML13", "OMVENDT", "EU_VARE", "EKSPORT" ] }, { "type": "null" } ] }, "discount": { "anyOf": [ { "type": "object", "properties": { "type": { "type": "string", "enum": [ "percent", "amount" ] }, "value": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": [ "type", "value" ], "additionalProperties": false }, { "type": "null" } ] }, "accountId": { "anyOf": [ { "type": "string", "maxLength": 100 }, { "type": "null" } ] }, "unit": { "anyOf": [ { "type": "string", "maxLength": 20 }, { "type": "null" } ] } }, "required": [ "description", "quantity", "unitPriceOere" ], "additionalProperties": false } } }, "required": [ "customerId", "validUntil", "lines" ], "additionalProperties": false}GET /v1/quotes/{quoteId}
Section titled “GET /v1/quotes/{quoteId}”| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
curl https://api.rieckflow.com/v1/quotes/9b2f1c1e-… \ -H "Authorization: Bearer $RIECK_API_KEY"const svar = await rieck.request("GET", "/v1/quotes/9b2f1c1e-…");{ "data": {}}acceptedBy is customer (through the quote link, with evidence) or creditor (recorded by you, with a note) — the two are not the same evidence. The signing code is never returned.application/jsonPossible errors 4
| HTTP | Code | Meaning |
|---|---|---|
| 401 | invalid_api_key | The API key is missing, invalid, expired or revoked. |
| 403 | api_not_included | The organisation’s plan does not include API access. |
| 403 | insufficient_scope | The key does not have the required scope. |
| 429 | rate_limited | The organisation’s rate budget is exhausted. |
DELETE /v1/quotes/{quoteId}
Section titled “DELETE /v1/quotes/{quoteId}”Drafts only (422 quote_not_deletable otherwise). A sent quote is a frozen record and cannot be deleted.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
curl -X DELETE https://api.rieckflow.com/v1/quotes/9b2f1c1e-… \ -H "Authorization: Bearer $RIECK_API_KEY" \ -H "Idempotency-Key: order-2041"const svar = await rieck.request("DELETE", "/v1/quotes/9b2f1c1e-…");Possible errors 7
| HTTP | Code | Meaning |
|---|---|---|
| 400 | invalid_idempotency_key | Idempotency-Key is missing or malformed. |
| 401 | invalid_api_key | The API key is missing, invalid, expired or revoked. |
| 403 | api_not_included | The organisation’s plan does not include API access. |
| 403 | insufficient_scope | The key does not have the required scope. |
| 409 | idempotency_conflict | The same key was used with a different request. |
| 409 | idempotency_in_progress | The same operation is currently being processed. Retry later. |
| 429 | rate_limited | The organisation’s rate budget is exhausted. |
POST /v1/quotes/{quoteId}/send
Section titled “POST /v1/quotes/{quoteId}/send”Freezes the content, seals the quote PDF (write-once) and sends the customer their link by e-mail when an address is on file. Calling it again RESENDS with a new link; the old link stops working.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
curl -X POST https://api.rieckflow.com/v1/quotes/9b2f1c1e-…/send \ -H "Authorization: Bearer $RIECK_API_KEY" \ -H "Idempotency-Key: order-2041"const svar = await rieck.request("POST", "/v1/quotes/9b2f1c1e-…/send");{ "data": {}}meta.delivery.channel is email or null; meta.delivery.url is the customer’s link — treat it as a secret, it IS the access — so you can deliver it through your own channel.application/jsonPossible errors 8
| HTTP | Code | Meaning |
|---|---|---|
| 400 | invalid_idempotency_key | Idempotency-Key is missing or malformed. |
| 401 | invalid_api_key | The API key is missing, invalid, expired or revoked. |
| 403 | api_not_included | The organisation’s plan does not include API access. |
| 403 | insufficient_scope | The key does not have the required scope. |
| 409 | idempotency_conflict | The same key was used with a different request. |
| 409 | idempotency_in_progress | The same operation is currently being processed. Retry later. |
| 422 | customer_email_missing | The invoice cannot be sent because the customer has no e-mail. |
| 429 | rate_limited | The organisation’s rate budget is exhausted. |
POST /v1/quotes/{quoteId}/order
Section titled “POST /v1/quotes/{quoteId}/order”Same operation as POST /v1/orders/from-quote, reached from the quote. The quote must be accepted; lines are copied. Idempotent per quote: an already converted quote returns its order with 200.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
curl -X POST https://api.rieckflow.com/v1/quotes/9b2f1c1e-…/order \ -H "Authorization: Bearer $RIECK_API_KEY" \ -H "Idempotency-Key: order-2041"const svar = await rieck.request("POST", "/v1/quotes/9b2f1c1e-…/order");{ "data": {}}Possible errors 7
| HTTP | Code | Meaning |
|---|---|---|
| 400 | invalid_idempotency_key | Idempotency-Key is missing or malformed. |
| 401 | invalid_api_key | The API key is missing, invalid, expired or revoked. |
| 403 | api_not_included | The organisation’s plan does not include API access. |
| 403 | insufficient_scope | The key does not have the required scope. |
| 409 | idempotency_conflict | The same key was used with a different request. |
| 409 | idempotency_in_progress | The same operation is currently being processed. Retry later. |
| 429 | rate_limited | The organisation’s rate budget is exhausted. |
POST /v1/quotes/{quoteId}/invoice
Section titled “POST /v1/quotes/{quoteId}/invoice”The short path without an order. The quote PDF (signed, when signed) and its attachments are attached to the invoice as documentation. Replay returns the same invoice with 200. A quote that became an order cannot also become an invoice (422 quote_not_accepted) — the same work only ever goes one way.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
curl -X POST https://api.rieckflow.com/v1/quotes/9b2f1c1e-…/invoice \ -H "Authorization: Bearer $RIECK_API_KEY" \ -H "Idempotency-Key: order-2041"const svar = await rieck.request("POST", "/v1/quotes/9b2f1c1e-…/invoice");{ "data": {}}data.invoiceId (also in Location) and data.quote.application/jsonPossible errors 7
| HTTP | Code | Meaning |
|---|---|---|
| 400 | invalid_idempotency_key | Idempotency-Key is missing or malformed. |
| 401 | invalid_api_key | The API key is missing, invalid, expired or revoked. |
| 403 | api_not_included | The organisation’s plan does not include API access. |
| 403 | insufficient_scope | The key does not have the required scope. |
| 409 | idempotency_conflict | The same key was used with a different request. |
| 409 | idempotency_in_progress | The same operation is currently being processed. Retry later. |
| 429 | rate_limited | The organisation’s rate budget is exhausted. |
GET /v1/quotes/{quoteId}/pdf
Section titled “GET /v1/quotes/{quoteId}/pdf”Exists only after sending (404 quote_pdf_not_found for a draft).
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
curl https://api.rieckflow.com/v1/quotes/9b2f1c1e-…/pdf \ -H "Authorization: Bearer $RIECK_API_KEY"const svar = await rieck.request("GET", "/v1/quotes/9b2f1c1e-…/pdf");Possible errors 4
| HTTP | Code | Meaning |
|---|---|---|
| 401 | invalid_api_key | The API key is missing, invalid, expired or revoked. |
| 403 | api_not_included | The organisation’s plan does not include API access. |
| 403 | insufficient_scope | The key does not have the required scope. |
| 429 | rate_limited | The organisation’s rate budget is exhausted. |
GET /v1/quotes/{quoteId}/attachments
Section titled “GET /v1/quotes/{quoteId}/attachments”| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
curl https://api.rieckflow.com/v1/quotes/9b2f1c1e-…/attachments \ -H "Authorization: Bearer $RIECK_API_KEY"const svar = await rieck.request("GET", "/v1/quotes/9b2f1c1e-…/attachments");{ "data": {}}type.application/jsonPossible errors 4
| HTTP | Code | Meaning |
|---|---|---|
| 401 | invalid_api_key | The API key is missing, invalid, expired or revoked. |
| 403 | api_not_included | The organisation’s plan does not include API access. |
| 403 | insufficient_scope | The key does not have the required scope. |
| 429 | rate_limited | The organisation’s rate budget is exhausted. |
POST /v1/quotes/{quoteId}/attachments
Section titled “POST /v1/quotes/{quoteId}/attachments”The contract, terms or correspondence the customer must see BEFORE signing. Base64 in JSON, max 10 MB, malware-scanned (422 malware_detected). Insert-only. Only sendWithQuote attachments present at send time go out with the e-mail; ALL of them follow the quote onto the invoice.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
Request body fields 5
| Field | Type | Required | Description |
|---|---|---|---|
filename | string | Yes | Field in the request payload. |
data | string | Yes | Field in the request payload. |
mime | string | Yes | Field in the request payload. |
sendWithQuote | boolean | No | Field in the request payload. |
type | string | No | Resource-specific type. |
curl -X POST https://api.rieckflow.com/v1/quotes/9b2f1c1e-…/attachments \ -H "Authorization: Bearer $RIECK_API_KEY" \ -H "Idempotency-Key: order-2041" \ -H "Content-Type: application/json" \ -d '{ "filename": "…", "data": "…", "mime": "application/pdf", "sendWithQuote": true, "type": "contract" }'const svar = await rieck.request("POST", "/v1/quotes/9b2f1c1e-…/attachments", { body: { "filename": "…", "data": "…", "mime": "application/pdf", "sendWithQuote": true, "type": "contract" },});{ "data": {}}Possible errors 9
| HTTP | Code | Meaning |
|---|---|---|
| 400 | invalid_idempotency_key | Idempotency-Key is missing or malformed. |
| 400 | invalid_request | The request body or parameter failed validation. |
| 401 | invalid_api_key | The API key is missing, invalid, expired or revoked. |
| 403 | api_not_included | The organisation’s plan does not include API access. |
| 403 | insufficient_scope | The key does not have the required scope. |
| 409 | idempotency_conflict | The same key was used with a different request. |
| 409 | idempotency_in_progress | The same operation is currently being processed. Retry later. |
| 413 | payload_too_large | The JSON or uploaded file exceeds this endpoint’s size limit. |
| 429 | rate_limited | The organisation’s rate budget is exhausted. |
Request body — fuldt JSON Schema
{ "type": "object", "properties": { "filename": { "type": "string", "minLength": 1, "maxLength": 255 }, "data": { "type": "string", "minLength": 1 }, "mime": { "type": "string", "enum": [ "application/pdf", "image/png", "image/jpeg", "image/webp" ] }, "sendWithQuote": { "default": true, "type": "boolean" }, "type": { "default": "other", "type": "string", "enum": [ "contract", "terms", "correspondence", "other" ] } }, "required": [ "filename", "data", "mime" ], "additionalProperties": false}GET /v1/quotes/{quoteId}/attachments/{attachmentId}
Section titled “GET /v1/quotes/{quoteId}/attachments/{attachmentId}”| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes | |
attachmentId | path | string | Yes |
curl https://api.rieckflow.com/v1/quotes/9b2f1c1e-…/attachments/9b2f1c1e-… \ -H "Authorization: Bearer $RIECK_API_KEY"const svar = await rieck.request("GET", "/v1/quotes/9b2f1c1e-…/attachments/9b2f1c1e-…");Possible errors 4
| HTTP | Code | Meaning |
|---|---|---|
| 401 | invalid_api_key | The API key is missing, invalid, expired or revoked. |
| 403 | api_not_included | The organisation’s plan does not include API access. |
| 403 | insufficient_scope | The key does not have the required scope. |
| 429 | rate_limited | The organisation’s rate budget is exhausted. |
GET /v1/quotes/{quoteId}/timeline
Section titled “GET /v1/quotes/{quoteId}/timeline”| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
curl https://api.rieckflow.com/v1/quotes/9b2f1c1e-…/timeline \ -H "Authorization: Bearer $RIECK_API_KEY"const svar = await rieck.request("GET", "/v1/quotes/9b2f1c1e-…/timeline");{ "data": {}}kind: created, sent, resent, viewed, signed, accepted, declined, expired, converted; actor: customer | user | system.application/jsonPossible errors 4
| HTTP | Code | Meaning |
|---|---|---|
| 401 | invalid_api_key | The API key is missing, invalid, expired or revoked. |
| 403 | api_not_included | The organisation’s plan does not include API access. |
| 403 | insufficient_scope | The key does not have the required scope. |
| 429 | rate_limited | The organisation’s rate budget is exhausted. |