API authentication, keys and scopes
Read time: 7 minutes. Who it's for: Developers integrating with QuotWay, and the store Admin who issues their keys.
⚠️ API keys require the Enterprise plan (a live trial counts). If a store later moves to a lower plan, its keys are kept but every request returns
402 plan_requireduntil the store is back on Enterprise.
How do I authenticate?
Every request carries one API key as a bearer token:
GET /v1/quotes HTTP/1.1
Host: api.quotway.com
Authorization: Bearer qw_live_2Xb9…
There is no OAuth flow, session or cookie. A key belongs to exactly one store, so the store is implied by the key - you never pass a shop domain. Keys are for server-to-server use; the API does not send CORS headers, so a browser page can't call it directly (and shouldn't: that would expose the key).
What does a key look like?
qw_live_<49 characters>
qw_test_<49 characters>
qw_live_keys work on any store.qw_test_keys are for Shopify development stores only (see Test keys).- The 49 characters are letters and digits: 43 random characters followed by a 6-character checksum. The checksum lets QuotWay (and secret scanners) reject a mistyped or truncated key instantly.
- The first 12 characters (for example
qw_live_2Xb9) are the key's display prefix - it's what you'll see in the admin, so you can tell keys apart without revealing them.
QuotWay stores only a keyed hash of each key. The full key is shown once, when it's created or rolled, and can never be shown again. If you lose it, roll or revoke it and create another.
Who can manage keys?
| Role | See the key list | Create, roll or revoke keys |
|---|---|---|
| Admin | Yes | Yes |
| Manager | Yes | No |
| Sales rep | Yes | No |
| View only | No | No |
Key management is Admin-only because a key is machine access to the store's quotes - and, with the
read_customer_data scope, to buyer personal data. That's an access decision, not a setting.
Creating a key also requires the Admin to accept the API Terms of Use for the store. QuotWay records who accepted which version, and when; a rolled key carries its predecessor's acceptance. If you tick Read buyer personal data, the form also warns that the key can read buyers' names, emails, phone numbers and addresses - and that anything it copies into another system is yours to keep secure and to delete when a buyer asks to be erased.
If the store moves below the Enterprise plan, its keys stop working (402 plan_required) but are
not deleted - they start working again after an upgrade. The API keys page still lists them,
with Revoke, so you can retire any you no longer trust.
Scopes
Grant each key only the scopes its integration needs. A request to an endpoint whose scope the key
lacks returns 403 insufficient_scope with the missing scope(s) in required_scopes.
| Scope | Label in the admin | Grants |
|---|---|---|
read_quotes |
Read quotes | Quotes, lines, totals, per-quote events and the events feed (GET /v1/quotes, /v1/quotes/{id}, /v1/quotes/{id}/events, /v1/events) |
read_customer_data |
Read buyer personal data | Adds the buyer's name, email, phone, addresses, custom-field answers and notes (the customer object and each line's buyer_note) to quote responses, allows the customer_email filter, and - together with read_quotes - unlocks quote PDFs (GET /v1/documents/{id}), which contain the same details. Only grant it to systems that need them. |
read_analytics |
Read analytics | GET /v1/analytics/summary |
write_quotes |
Create quotes and post messages | POST /v1/quotes, POST /v1/quotes/{id}/messages, POST /v1/quotes/{id}/send-proposal |
manage_webhooks |
Manage webhooks | GET/POST /v1/webhooks, GET/DELETE /v1/webhooks/{id} |
GET /v1/ping needs no scope - any valid key works - and returns the key's scopes.
read_customer_data only widens what read_quotes returns (and adds documents); it doesn't grant
access to anything on its own. A key with write_quotes but not read_quotes can still create a quote - the 201
response contains the new quote - but can't list or fetch quotes afterwards.
Test keys
Tick Test key (qw_test_) when creating a key on a Shopify development store (the option only appears there). A test key:
- only works on development stores - used against a live store it returns
401 test_key_on_live_store; - works on the development store's real QuotWay data. There is no separate sandbox: a quote you create with a test key is a real quote in that store.
The prefix exists so that code, logs and config make it obvious which key is which.
Expiry
Choose Never, In 30 days, In 90 days or In 1 year when you create a key. After the
expiry time the key returns 401 invalid_api_key. A key within 24 hours of expiring shows
Expiring soon in the admin. Expired and revoked keys stay visible in the list for 30 days, then
drop off.
IP allowlist
Optionally restrict a key to the IP addresses your integration calls from. In Allowed IP addresses, enter up to 20 addresses, one per line. Leave it empty to allow any IP.
- Entries are exact IPv4 or IPv6 addresses. CIDR ranges aren't supported - list each egress address.
- A request from any other address returns
403 ip_not_allowed. - The allowlist is checked after the key itself, so an invalid key still gets
401.
Rolling a key (zero-downtime rotation)
Select Roll on an active key to replace it without an outage:
- QuotWay creates a new key with the same name, scopes, test flag and IP allowlist, and shows it once.
- The old key keeps working for 24 hours (or until its own expiry, if that's sooner), then stops.
- Deploy the new key within that window.
If the old key had an expiry, the new key gets the same lifetime, counted from the moment you roll.
A key can be rolled once. To rotate again, roll the replacement.
Revoking a key
Select Revoke, then Confirm revoke, to stop a key immediately. Every request with it returns
401 invalid_api_key from then on. Revoking can't be undone - create a new key if you need access
again. Revoke rather than roll if you think a key has leaked.
What happens if the store uninstalls QuotWay?
Uninstalling QuotWay revokes every API key for the store (and disables its webhook endpoints).
Reinstalling doesn't bring them back - an Admin creates new keys. A key for a store that isn't
actively installed returns 401 invalid_api_key.
Limits
- Up to 10 active keys per store. Revoke one to create another.
- Each key is rate-limited on its own, and all of a store's keys share a store-wide limit - see Rate limits.
Seeing what a key has done
In Settings → Integrations → API keys, the key list shows each key's Last used time, and
the Requests button opens its recent requests (the last 100): time, method, route, status, duration and the request_id.
QuotWay logs the route template (for example /v1/quotes/{id}), never request or response bodies.
When you contact support about a failed call, quote the request_id from the response body or the
X-Request-Id header.
Security checklist
- Keep keys server-side, in a secrets manager or environment variable. Never ship one in browser or mobile code, and never commit one to a repository.
- One key per integration, named after it, so you can revoke one system without breaking the rest.
- Least privilege: leave out
read_customer_dataunless the integration needs buyer contact details, andwrite_quotesunless it creates quotes or messages. - Use an IP allowlist when your integration has fixed egress addresses.
- Roll keys on a schedule and whenever someone with access leaves.
Related
- Errors -
invalid_api_key,insufficient_scope,ip_not_allowedand the rest. - The quote object - what
read_customer_dataadds. - Staff and roles
Brauchen Sie noch Hilfe? Das Team hilft gern weiter.