API Reference
Generate proposals from your own systems
Describe an event in plain language and get back a costed proposal, priced from your own equipment catalogue — the same engine the app uses. Available on the Business plan.
Authentication
Create a key in Settings → API keys. It is shown once; we store only a hash, so it cannot be retrieved later. Send it as a bearer token on every request.
Authorization: Bearer cq_live_xxxxxxxxxxxxxxxxxxxxxxxxKeys carry the permissions of the company they belong to and nothing else. A key can never read or write another account's data. Revoking a key in Settings takes effect immediately.
Base URL
https://api.cuequote.comCreate a proposal
POST/v1/proposals
The only required field is event.description. Everything else improves the result: attendee count and duration drive equipment quantities, and the venue affects regional pricing.
curl -X POST https://api.cuequote.com/v1/proposals \
-H "Authorization: Bearer $CUEQUOTE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Warsaw Tech Summit 2026",
"client": { "name": "Acme Events", "email": "ops@acme.example" },
"event": {
"description": "Two-day tech summit, 200 attendees, main stage with LED
and simultaneous interpretation, plus two breakout rooms.",
"date": "2026-11-03",
"venue": "Warsaw",
"attendees": 200,
"days": 2
}
}'Response — 201 Created
{
"id": "4b888edb-d71a-4aa1-87fb-26ba1d3fc103",
"status": "draft",
"title": "Warsaw Tech Summit 2026",
"currency": "PLN",
"subtotal": 40010,
"total": 40010,
"scope_summary": "Two-day summit with a main stage ...",
"line_items": [
{
"category": "video",
"name": "LED Wall Panel (P2.6)",
"quantity": 21,
"unit": "day",
"unit_price": 350,
"is_optional": false
}
],
"share_url": "https://app.cuequote.com/share/961419b1-...",
"app_url": "https://app.cuequote.com/proposals/4b888edb-...",
"quota": { "used": 8, "limit": 120 }
}The proposal is created as a draft. It appears in the app immediately, editable like any other, and nothing is sent to the client until you send it.
| Field | Type | Notes |
|---|---|---|
| event.description | string | Required. Up to 10,000 characters. |
| event.date | string | YYYY-MM-DD. |
| event.venue | string | City or venue name. Affects regional pricing. |
| event.attendees | number | Drives equipment sizing. |
| event.days | number | Defaults to 1. |
| title | string | Optional. Generated from the venue and size if omitted. |
| client | object | Creates a new client. Use client_id instead to attach an existing one. |
| currency | string | Defaults to your company currency. |
Fetch a proposal
GET/v1/proposals/{id}
curl https://api.cuequote.com/v1/proposals/4b888edb-... \
-H "Authorization: Bearer $CUEQUOTE_API_KEY"Returns the proposal with its line items and current status.
List proposals
GET/v1/proposals
Newest first, without line items. Pass since to fetch only what has appeared since your last check — the usual way to drive an integration without re-reading everything.
curl "https://api.cuequote.com/v1/proposals?since=2026-08-01T00:00:00Z&status=accepted&limit=50" \
-H "Authorization: Bearer $CUEQUOTE_API_KEY"| Query | Notes |
|---|---|
| since | ISO 8601 timestamp. Returns proposals created strictly after it. |
| status | Filter to one status, e.g. accepted. |
| limit | 1–100, defaults to 25. |
For anything time-sensitive, prefer webhooks over polling — you hear about an acceptance in about a second instead of whenever you next look.
Equipment availability
GET/v1/inventory/availability
How many of each tracked product are free on each day, after confirmed jobs, repairs, losses and equipment not yet back. Quotes that are sent but not won are reported as provisional and do not reduce free. These are the same numbers as the Availability tab in the app.
free can be negative: that means the product is overbooked for that day, with more firm and overdue quantity out than owned.
curl "https://api.cuequote.com/v1/inventory/availability?from=2026-10-12&to=2026-10-18" \
-H "Authorization: Bearer $CUEQUOTE_API_KEY"| Query | Notes |
|---|---|
| from | First day, YYYY-MM-DD, inclusive. |
| to | Last day, YYYY-MM-DD, inclusive, at most 366 days after from. |
| items | Optional. Comma-separated catalog item ids, up to 200. Defaults to every tracked product. Any id that does not exist, is not tracked, or belongs to another company is simply left out of the response: it never causes an error. |
{
"data": [
{ "day": "2026-10-12", "catalog_item_id": "0b7c...", "owned": 8, "in_repair": 1, "lost": 0,
"firm": 6, "provisional": 2, "overdue": 0, "free": 1 }
],
"count": 1
}The number of products this resolves to (every tracked product, or the ones named in items that belong to your company), multiplied by the number of days in the range, must be at most 20,000. A request over that ceiling returns 400. Ask about a shorter from/to range, or pass items to narrow the products, to bring it under the limit.
Returns 400 invalid_request when from or to is missing, not YYYY-MM-DD, or an impossible calendar date such as 2026-02-30, when to is before from or more than 366 days after it, when items is present but empty, malformed, or lists more than 200 ids, or when the product-days ceiling above is exceeded.
Check a key
GET/v1/me
Returns the account a key belongs to. Cheap and instant — use it to verify a key works rather than generating a proposal, which takes about a minute and counts against your allowance.
{
"company_id": "f5afe678-...",
"company_name": "Nordic Stage AV",
"currency": "PLN",
"country": "PL",
"plan": "business"
}Subscribe to events
POST/v1/webhooks·DELETE/v1/webhooks/{id}
The same endpoints you can add in Settings, managed programmatically — which is what platforms like Zapier need in order to subscribe on your behalf.
curl -X POST https://api.cuequote.com/v1/webhooks \
-H "Authorization: Bearer $CUEQUOTE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/cuequote",
"events": ["proposal.accepted"]
}'
# -> { "id": "...", "url": "...", "events": [...], "signing_secret": "whsec_..." }The signing secret is returned once, at creation. Keep it — it is what lets you verify a delivery came from us. Omit events to subscribe to all four. Endpoints must be https and publicly addressable. See the webhook guide for payloads and signature verification.
Errors
Every error returns a JSON body with a stable code and a human-readable message. Match on the code, not the message.
{ "error": { "code": "quota_exceeded", "message": "...", "used": 120, "limit": 120 } }| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | No bearer key supplied. |
| 401 | invalid_key | Key is wrong or has been revoked. |
| 400 | invalid_request | Missing or oversized field. |
| 403 | plan_required | API access is on the Business plan. |
| 403 | subscription_inactive | Payment is past due or cancelled. |
| 404 | not_found | No such proposal or client on this account. |
| 422 | empty_catalog | Add equipment first — pricing comes from your own rates. |
| 429 | rate_limited | More than 60 requests in an hour. |
| 429 | quota_exceeded | Monthly proposal allowance used. |
| 502 | generation_failed | The generator did not return a usable proposal. Retry. |
Rate limits and quota
60 requests per hour per key. Generation runs a language model over your catalogue, so this is a spend control as much as an abuse control.
Proposals count against your monthly plan allowance, the same as ones created in the app — 120 a month on Business. The API is another door to the same engine, not a separate budget. Every response includes a quota object so you can track it without a second call.
Generation typically takes 20–60 seconds depending on event complexity. Set your client timeout to at least 90 seconds.
Need something not here?
The website quote form puts this same engine on your own site with one script tag. Or connect it to an AI assistant over MCP. Webhooks and Zapier are on the roadmap. Tell us what you are building at hello@cuequote.com and it will shape what ships next.