Merchant API
Authenticate merchant-owned systems, use the Qrivo API, and handle responses safely.
Merchant API access is intended for eligible merchants connecting a trusted server-side system to their own Qrivo workspace. A key can access only the Shopify store that created it.
Create an API key
- Open Qrivo → Settings and find the Merchant API section.
- Enter a name that identifies the integration.
- Select only the scopes the integration needs.
- Create the key and copy the token immediately.
- Store the token in a server-side secret manager.
Tokens are shown once
If you lose a token, revoke that key and create a replacement. Never place a token in a URL, storefront script, browser bundle, repository, screenshot, or log.
Scopes
| Scope | Allows |
|---|---|
qr:read | List and read QR codes. |
qr:write | Create QR codes. |
qr:manage | Update dynamic QR codes. |
campaigns:read | List and read campaigns. |
campaigns:write | Create and update campaigns. |
analytics:read | Read the analytics summary. |
webhooks:read | List webhook subscriptions. |
webhooks:write | Create and delete webhook subscriptions. |
Make a request
The production API origin is https://app.qrivo.solidcraftlabs.com. API routes are versioned under /api/v1. Use that origin for live integrations. Settings shows the origin for the current install if you are on a non-production environment.
export QRIVO_API_ORIGIN=https://app.qrivo.solidcraftlabs.com
curl "$QRIVO_API_ORIGIN/api/v1/qr-codes" \
--header "Authorization: Bearer $QRIVO_API_TOKEN" \
--header "Accept: application/json"For JSON requests, also send Content-Type: application/json.
Endpoint reference
| Method and path | Scope | Behavior |
|---|---|---|
GET /api/v1/qr-codes | qr:read | Lists the shop's QR codes and a continuation cursor when present. |
POST /api/v1/qr-codes | qr:write | Creates a static or dynamic QR within the active plan quota. |
GET /api/v1/qr-codes/:id | qr:read | Returns one QR code owned by the shop. |
PATCH /api/v1/qr-codes/:id | qr:manage | Updates an eligible dynamic QR code. Static codes are immutable. |
GET /api/v1/campaigns | campaigns:read | Lists the shop's campaigns. |
POST /api/v1/campaigns | campaigns:write | Creates a campaign. |
GET /api/v1/campaigns/:id | campaigns:read | Returns one campaign owned by the shop. |
PATCH /api/v1/campaigns/:id | campaigns:write | Updates a campaign's name, description, or status. |
GET /api/v1/webhooks | webhooks:read | Lists subscriptions without returning signing secrets. |
POST /api/v1/webhooks | webhooks:write | Creates a subscription for a public HTTPS endpoint. |
DELETE /api/v1/webhooks/:id | webhooks:write | Deletes a subscription. |
GET /api/v1/analytics/summary | analytics:read | Returns a summary of QR, scan, and campaign activity. |
Examples
Create a dynamic QR code
The destination must be an eligible HTTPS URL for the authenticated store. Use static only when you need a permanent, non-trackable destination.
curl "$QRIVO_API_ORIGIN/api/v1/qr-codes" \
--request POST \
--header "Authorization: Bearer $QRIVO_API_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"destination": "https://your-store.myshopify.com/products/example",
"note": "Fall window display",
"qrType": "dynamic"
}'Pause a dynamic QR code
curl "$QRIVO_API_ORIGIN/api/v1/qr-codes/$QR_ID" \
--request PATCH \
--header "Authorization: Bearer $QRIVO_API_TOKEN" \
--header "Content-Type: application/json" \
--data '{"status":"paused"}'Create a campaign
curl "$QRIVO_API_ORIGIN/api/v1/campaigns" \
--request POST \
--header "Authorization: Bearer $QRIVO_API_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"name": "Fall retail launch",
"description": "QR placements for the fall collection"
}'Responses and errors
Successful JSON responses use a top-level data field. Lists may also include nextCursor. Error responses include a stable error value and may include a human-readable message.
| Status | Meaning | Recommended action |
|---|---|---|
200, 201, 204 | Read/update, created, or deleted successfully | Process the response. A 204 response has no useful body. |
400 | Request body, URL, or destination is invalid | Correct the request; do not retry it unchanged. |
401 | Token is missing, invalid, or revoked | Check the server-side secret or replace the key. |
403 | Plan or API-key scope does not allow the action | Use an appropriately scoped key or review the plan. |
404 | Route or shop-owned record does not exist | Check the path and record ID. |
409 | A plan limit or state conflict prevents the action | Review the limit or avoid modifying a static code. |
429 | The shop exceeded its current request window | Wait until the current minute ends, then retry with backoff. |
Successful authenticated responses expose ratelimit-remaining and ratelimit-reset. The reset value is a Unix timestamp in seconds. 429 responses do not currently include those headers. Rate limits and plan quotas are separate controls; consult Qrivo's Plans screen for current limits.
Security checklist
- Create separate keys for separate systems and environments.
- Use the smallest possible scope set.
- Rotate keys after suspected exposure and revoke unused keys.
- Apply timeouts, bounded retries, and idempotency.
- Avoid logging complete requests that may contain tokens or private notes.
- Never expose the API through untrusted client-side code without your own authenticated server.
