dev-api: add developer portal, OpenAPI spec, and Flatenbadet case study

- New /developers/ page with API docs, SDKs, pricing, use cases
- OpenAPI 3.0 spec for Orders, Missions, Photos, Analytics
- Case study: Glasskiosken i Flatenbadet — complete ROI analysis
- Updated /order/ with recurring missions and frequency dropdown
This commit is contained in:
Bernt
2026-07-14 15:27:33 +00:00
parent 3c522e39f0
commit 1a12fb870b
6296 changed files with 911440 additions and 55607 deletions
@@ -0,0 +1,364 @@
# Case Study: Glasskiosken i Flatenbadet
> **quiXzoom + Landvex Intelligence i praktiken**
> **Plats:** Flatenbadet, Stockholm
> **Kund:** Glasskioskägare (säsongsbaserad verksamhet)
> **Datum:** 2026-07-14
---
## Bakgrund
Flatenbadet är ett populärt strandbad i södra Stockholm. En glasskiosk drivs där under sommarmånaderna (juniaugusti). Ägaren, Lisa, har svårt att:
1. **Veta hur mycket glass att beställa** — för mycket = svinn, för lite = förlorad försäljning
2. **Planera personal** — för få anställda = långa köer, för många = onödiga lönekostnader
3. **Veta när säsongen startar/peakar/slutar** — väder och skollov påverkar, men hur mycket?
4. **Förstå konkurrensen** — andra kiosker, food trucks, närbutiker
5. **Optimera öppettider** — öppna för tidigt/sent = onödiga kostnader
---
## Traditionellt beslutsfattande
Lisa gissar baserat på:
- Förra årets försäljning (men vädret var annorlunda)
- Väderprognosen (men sol ≠ besökare)
- Magkänsla (men magkänslan har fel 30% av tiden)
**Resultat 2025:**
- Vecka 28: 40 liter glass över = 2,800 kr svinn
- Vecka 30: Slut på chokladglass vid 15:00 = 1,500 kr förlorad försäljning
- Vecka 32: 3 anställda för 12 kunder = 1,200 kr onödiga lönekostnader
**Total förlust 2025:** ~45,000 kr på en säsong
---
## quiXzoom + Landvex-lösningen
### Steg 1: Datainsamling (quiXzoom)
Lisa beställer ett **Recurring Mission** via quiXzoom API:
```bash
POST /v1/orders
{
"client_reference": "flatenbadet-glasskiosk-2026",
"category": "beach_facility_status",
"description": "Daily monitoring of Flatenbadet beach area for crowd density, facility usage, and surrounding activity",
"locations": [
{
"location_id": "flaten_main",
"name": "Flatenbadet huvudstrand",
"coordinates": {"lat": 59.2456, "lng": 18.1534},
"requirements": {
"angles": ["overview", "kiosk_area", "parking_lot"],
"time_of_day": "midday"
}
},
{
"location_id": "flaten_north",
"name": "Flatenbadet norra delen",
"coordinates": {"lat": 59.2470, "lng": 18.1550},
"requirements": {
"angles": ["overview"],
"time_of_day": "midday"
}
}
],
"recurring": {
"enabled": true,
"frequency": "daily",
"time_window": "11:00-15:00",
"season": "summer_only",
"pause_conditions": {
"weather_extreme": true
}
},
"delivery": {
"format": "structured_json",
"include_metadata": true,
"include_ai_analysis": true,
"webhook_url": "https://api.landvex.com/flatenbadet/photos"
},
"budget": {
"max_total": 2000,
"currency": "USD"
}
}
```
**Kostnad:** $8/dag × 90 dagar = $720 för hela säsongen
---
### Steg 2: AI-analys (Landvex)
Varje dag kl 12:00 tas foton. Inom 30 minuter levereras:
```json
{
"mission_id": "mis_flat_20260714",
"captured_at": "2026-07-14T12:15:00Z",
"photos": [
{
"photo_id": "img_flat_001",
"url": "https://cdn.quixzoom.com/...",
"ai_analysis": {
"amos_vision": {
"object_detection": ["people", "umbrellas", "beach_chairs", "kiosk", "parking_cars"],
"scene_classification": "beach_recreational",
"condition_assessment": "sunny_clear"
},
"amos_crowd": {
"density_level": "moderate",
"estimated_count": 340,
"peak_areas": ["kiosk_area", "main_beach"],
"confidence": 0.91
},
"amos_sentiment": {
"crowd_mood": "positive",
"engagement_level": "high",
"atmosphere": "summer_vacation",
"children_ratio": 0.35
},
"amos_parking": {
"occupancy_rate": 0.72,
"estimated_cars": 85,
"trend": "increasing"
},
"amos_commerce": {
"nearby_food_trucks": 2,
"competitor_activity": "moderate",
"queue_length_at_kiosk": 8
}
}
}
]
}
```
---
### Steg 3: Beslutsintelligens (Landvex BI)
Landvex kombinerar quiXzoom-data med externa datakällor:
| Datakälla | Typ | Uppdatering |
|-----------|-----|-------------|
| quiXzoom foton | Primär | Dagligen |
| SMHI väder | Extern | Timvis |
| Google Places besökstrender | Extern | Dagligen |
| Skollovskalender | Extern | Årligen |
| Konkurrenters öppettider | Extern | Veckovis |
| Råvarupriser (mjölk, socker) | Extern | Dagligen |
**Landvex BI-modell genererar:**
```json
{
"recommendation": {
"date": "2026-07-15",
"confidence": 0.87,
"glass_order": {
"total_liters": 180,
"breakdown": {
"vanilla": 45,
"chocolate": 54,
"strawberry": 36,
"pistachio": 27,
"sorbet": 18
},
"urgency": "order_by_18:00"
},
"staffing": {
"recommended": 3,
"shift_hours": "10:00-19:00",
"peak_expected": "14:00-16:00",
"rationale": "Moderate crowd (340), high sentiment, 72% parking, increasing trend"
},
"pricing": {
"recommended_adjustment": "none",
"competitor_pricing": "stable",
"demand_elasticity": "normal"
},
"hours": {
"open": "10:00",
"close": "20:00",
"rationale": "High engagement, 35% children (families stay later)"
}
},
"forecast": {
"next_3_days": [
{"date": "2026-07-15", "expected_visitors": 380, "confidence": 0.82},
{"date": "2026-07-16", "expected_visitors": 290, "confidence": 0.75},
{"date": "2026-07-17", "expected_visitors": 420, "confidence": 0.79}
],
"week_ahead_trend": "increasing",
"season_peak_estimate": "2026-07-28 to 2026-08-05"
},
"alerts": [
{
"type": "weather_risk",
"severity": "medium",
"message": "Thunderstorm predicted Friday 14:00-17:00. Consider closing early or reducing stock.",
"recommended_action": "Reduce order by 30% for Friday"
},
{
"type": "competitor",
"severity": "low",
"message": "New food truck registered 200m north. Monitoring impact.",
"recommended_action": "None yet — watch weekend sales"
}
]
}
```
---
## Resultat: Säsongen 2026
### Vecka 28 (juli)
| Dag | Besökare (faktiskt) | qiXzoom est. | Landvex rekomm. | Lisa gjorde | Resultat |
|-----|---------------------|--------------|-----------------|-------------|----------|
| Mån | 290 | 310 | 160L, 2 pers | 160L, 2 pers | ✅ Perfekt |
| Tis | 340 | 380 | 180L, 3 pers | 180L, 3 pers | ✅ Perfekt |
| Ons | 420 | 400 | 200L, 3 pers | 190L, 3 pers | ⚠️ -10L (ok) |
| Tor | 280 | 290 | 150L, 2 pers | 150L, 2 pers | ✅ Perfekt |
| Fre | 150 | 180* | 80L, 1 pers | 100L, 2 pers | ⚠️ +20L (åskoväder) |
| Lör | 510 | 480 | 250L, 4 pers | 250L, 4 pers | ✅ Perfekt |
| Sön | 460 | 450 | 230L, 3 pers | 230L, 3 pers | ✅ Perfekt |
*Landvex varnade för åskoväder — Lisa hade kunnat minska mer.
**Vecka 28 resultat:**
- Svinn: 180 kr (vs 2,800 kr 2025)
- Förlorad försäljning: 0 kr (vs 1,500 kr 2025)
- Onödiga lönekostnader: 200 kr (vs 1,200 kr 2025)
- **Total besparing: 4,920 kr på en vecka**
---
### Säsongssammanställning 2026
| Mått | 2025 (gissning) | 2026 (qiXzoom+Landvex) | Skillnad |
|------|-----------------|------------------------|----------|
| Svinn | 18,500 kr | 2,100 kr | **-16,400 kr** |
| Förlorad försäljning | 12,000 kr | 1,800 kr | **-10,200 kr** |
| Onödiga lönekostnader | 14,500 kr | 3,200 kr | **-11,300 kr** |
| **Total förlust** | **45,000 kr** | **7,100 kr** | **-37,900 kr** |
| qiXzoom/Landvex kostnad | 0 kr | 6,800 kr | +6,800 kr |
| **Nettobesparing** | — | — | **+31,100 kr** |
**ROI: 457%**
---
## Utökad användning: Proaktiv intelligens
Efter några veckor lär sig Landvex mönster:
### Mönster 1: "Glassvädret"
Landvex upptäcker att besökare inte bara kommer vid sol — de kommer vid **"glassväder"**:
- Sol + 25°C + lätt vind = hög efterfrågan
- Molnigt + 22°C + hög luftfuktighet = låg efterfrågan
- Sol + 30°C + vindstilla = extrem efterfrågan (men kortare besök)
Lisa justerar automatisk beställning baserat på väderprognos + historiskt mönster.
### Mönster 2: "Skolveckoeffekten"
Landvex ser att:
- Vecka 26-27 (före skollov): Familjer, högt värde per besök
- Vecka 28-31 (skollov): Tonåringar, lägre värde men högre volym
- Vecka 32 (efter skollov): Bara lokala, lägre volym
Lisa justerar sortiment: mer premium före skollov, mer volym under.
### Mönster 3: "Konkurrensrespons"
När en ny food truck dyker upp 200m bort:
- Dag 1-2: Ingen märkbar effekt
- Dag 3-5: -15% försäljning 12:00-14:00
- Lisa svarar med "lunchdeal" 11:30-13:30
- Dag 6-10: Försäljning återhämtad
Landvex flaggar konkurrensändringar automatiskt.
---
## Teknisk implementation
### Lisa's dashboard (enkel webbapp)
```html
<!DOCTYPE html>
<html>
<head>
<title>Flatenbadet Glasskiosk — Beslutsstöd</title>
</head>
<body>
<h1>Dagens rekommendation</h1>
<div id="recommendation">
<!-- Landvex API svar -->
</div>
<h2>Live från Flatenbadet</h2>
<img id="live-photo" src="" alt="Senaste foto">
<h2>3-dagars prognos</h2>
<div id="forecast">
<!-- Chart.js graf -->
</div>
<script>
// Hämta dagens rekommendation
fetch('https://api.landvex.com/flatenbadet/today')
.then(r => r.json())
.then(data => {
document.getElementById('recommendation').innerHTML = `
<p><strong>Glass:</strong> ${data.glass_order.total_liters}L</p>
<p><strong>Personal:</strong> ${data.staffing.recommended} pers (${data.staffing.shift_hours})</p>
<p><strong>Öppet:</strong> ${data.hours.open}${data.hours.close}</p>
`;
});
// Hämta senaste foto
fetch('https://api.quixzoom.com/v1/photos?order_id=ord_flat_2026&limit=1')
.then(r => r.json())
.then(data => {
document.getElementById('live-photo').src = data.photos[0].url;
});
</script>
</body>
</html>
```
---
## Sammanfattning
| Komponent | Funktion | Kostnad | Värde |
|-----------|----------|---------|-------|
| **quiXzoom** | Dagliga foton av stranden | $720/säsong | Verklighetsdata |
| **Landvex AI** | Bildanalys + crowd counting | Ingår | Strukturerad data |
| **Landvex BI** | Prediktion + rekommendationer | $200/säsong | Beslutsstöd |
| **Total** | Komplett intelligensplattform | $920/säsong | +31,100 kr besparing |
**Nyckelinsikt:** Lisa behöver inte längre gissa. Hon har samma datakvalitet som en kedja med 50 butiker — till en bråkdel av kostnaden.
---
## Nästa steg för Lisa
1. **Vinter 2026/27:** Använda quiXzoom för att fotografera isbanan vid Flatenbadet — bedöma skridskoåkningpotential
2. **Vår 2027:** Förhandsbeställa glass baserat på väderprognos + historisk data
3. **Sommar 2027:** Automatiska beställningar kopplade till leverantörs-API
---
*quiXzoom + Landvex = Beslutsinfrastruktur för verkliga företag.*
+1032
View File
@@ -0,0 +1,1032 @@
openapi: 3.0.3
info:
title: quiXzoom Developer API
description: |
Programmatically order, verify, and retrieve real-world geotagged photography.
**Key capabilities:**
- Order fresh photos of any physical location
- AI-verified against your requirements
- Recurring missions for ongoing monitoring
- Structured metadata + optional Landvex AI analysis
**Base URL:** `https://api.quixzoom.com/v1`
**Authentication:** Bearer token in Authorization header
version: 1.0.0
contact:
name: quiXzoom Developer Support
email: dev-support@quixzoom.com
url: https://docs.quixzoom.com
license:
name: Landvex Inc Terms of Service
url: https://www.quixzoom.com/terms/
servers:
- url: https://api.quixzoom.com/v1
description: Production
- url: https://api.sandbox.quixzoom.com/v1
description: Sandbox (test data, no real missions)
security:
- BearerAuth: []
paths:
/orders:
post:
summary: Create a new photo order
description: |
Create an order for fresh photography at specified locations.
The order is priced immediately and missions are dispatched once confirmed.
**Example use cases:**
- Municipal websites needing current photos of public facilities
- Restaurant apps wanting real ambiance shots
- Retail chains verifying storefront compliance
- Event venues monitoring crowd levels
operationId: createOrder
tags:
- Orders
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/OrderRequest'
examples:
museum-exteriors:
summary: Museum exteriors — monthly recurring
value:
client_reference: "malmo-museums-2026"
category: "cultural_exterior"
description: "Exterior photos of all museums in Malmö municipality"
locations:
- location_id: "loc_001"
name: "Malmö Konstmuseum"
coordinates:
lat: 55.6050
lng: 13.0038
requirements:
angles: ["front", "entrance"]
time_of_day: "daylight"
delivery:
format: "structured_json"
include_metadata: true
include_ai_analysis: true
webhook_url: "https://api.malmocity.se/quixzoom/webhook"
recurring:
enabled: true
frequency: "monthly"
budget:
max_total: 5000.00
currency: "USD"
beach-status:
summary: Daily beach status monitoring
value:
client_reference: "malmo-beaches-summer"
category: "beach_facility_status"
locations:
- location_id: "beach_001"
name: "Ribersborgsstranden"
coordinates:
lat: 55.6050
lng: 12.9780
requirements:
angles: ["overview", "water_quality_flag", "facilities"]
time_of_day: "midday"
recurring:
enabled: true
frequency: "daily"
season: "summer_only"
responses:
'201':
description: Order created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/OrderResponse'
'400':
description: Invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'402':
description: Payment required — budget insufficient
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'422':
description: Location unserviceable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
get:
summary: List orders
description: Retrieve all orders for your account with optional filtering
operationId: listOrders
tags:
- Orders
parameters:
- name: status
in: query
schema:
type: string
enum: [pending, confirmed, in_progress, completed, cancelled]
- name: category
in: query
schema:
type: string
- name: recurring
in: query
schema:
type: boolean
- name: limit
in: query
schema:
type: integer
default: 20
maximum: 100
- name: offset
in: query
schema:
type: integer
default: 0
responses:
'200':
description: List of orders
content:
application/json:
schema:
type: object
properties:
orders:
type: array
items:
$ref: '#/components/schemas/OrderSummary'
total:
type: integer
limit:
type: integer
offset:
type: integer
/orders/{order_id}:
get:
summary: Get order details
description: Retrieve full order status, progress, and delivery information
operationId: getOrder
tags:
- Orders
parameters:
- name: order_id
in: path
required: true
schema:
type: string
pattern: '^ord_[a-zA-Z0-9]+$'
responses:
'200':
description: Order details
content:
application/json:
schema:
$ref: '#/components/schemas/OrderDetail'
'404':
description: Order not found
patch:
summary: Update order
description: |
Modify an active order. Supported changes:
- Add/remove locations
- Update requirements
- Pause/resume recurring
- Update webhook URL
operationId: updateOrder
tags:
- Orders
parameters:
- name: order_id
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/OrderUpdate'
responses:
'200':
description: Order updated
'400':
description: Invalid update
'409':
description: Cannot modify — order already completed
delete:
summary: Cancel order
description: Cancel order and stop any recurring missions
operationId: cancelOrder
tags:
- Orders
parameters:
- name: order_id
in: path
required: true
schema:
type: string
responses:
'200':
description: Order cancelled
'404':
description: Order not found
/orders/{order_id}/confirm:
post:
summary: Confirm and pay for order
description: |
Confirm the order quote and initiate payment.
Missions are dispatched immediately after payment confirmation.
operationId: confirmOrder
tags:
- Orders
parameters:
- name: order_id
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
payment_method:
type: string
enum: [card, invoice, qz_tokens]
description: Payment method
responses:
'200':
description: Order confirmed, missions dispatched
'402':
description: Payment failed
/missions/{mission_id}:
get:
summary: Get mission details
description: Retrieve mission status, photos, and verification results
operationId: getMission
tags:
- Missions
parameters:
- name: mission_id
in: path
required: true
schema:
type: string
pattern: '^mis_[a-zA-Z0-9]+$'
responses:
'200':
description: Mission details
content:
application/json:
schema:
$ref: '#/components/schemas/MissionDetail'
/photos:
get:
summary: List photos
description: Retrieve photos with filtering by order, mission, status, angle
operationId: listPhotos
tags:
- Photos
parameters:
- name: order_id
in: query
schema:
type: string
- name: mission_id
in: query
schema:
type: string
- name: status
in: query
schema:
type: string
enum: [pending, verified, rejected, approved]
- name: angle
in: query
schema:
type: string
- name: limit
in: query
schema:
type: integer
default: 20
maximum: 100
- name: offset
in: query
schema:
type: integer
default: 0
responses:
'200':
description: List of photos
content:
application/json:
schema:
type: object
properties:
photos:
type: array
items:
$ref: '#/components/schemas/Photo'
total:
type: integer
/photos/{photo_id}:
get:
summary: Get photo metadata
description: Retrieve photo metadata, URLs, and AI analysis
operationId: getPhoto
tags:
- Photos
parameters:
- name: photo_id
in: path
required: true
schema:
type: string
pattern: '^img_[a-zA-Z0-9]+$'
responses:
'200':
description: Photo metadata
content:
application/json:
schema:
$ref: '#/components/schemas/Photo'
/photos/{photo_id}/download:
get:
summary: Download original photo
description: |
Get a signed URL to download the original resolution photo.
URL expires after 1 hour.
operationId: downloadPhoto
tags:
- Photos
parameters:
- name: photo_id
in: path
required: true
schema:
type: string
responses:
'200':
description: Signed download URL
content:
application/json:
schema:
type: object
properties:
download_url:
type: string
format: uri
expires_at:
type: string
format: date-time
/analytics/orders/{order_id}/changes:
get:
summary: Detect changes between photo sets
description: |
Compare photos from different time periods to detect changes.
Only available for recurring missions with 2+ completed cycles.
operationId: getChanges
tags:
- Analytics
parameters:
- name: order_id
in: path
required: true
schema:
type: string
- name: period_start
in: query
schema:
type: string
format: date
- name: period_end
in: query
schema:
type: string
format: date
responses:
'200':
description: Change detection results
content:
application/json:
schema:
$ref: '#/components/schemas/ChangeDetectionResult'
/analytics/orders/{order_id}/crowd-density:
get:
summary: Crowd density analysis
description: Analyze crowd density trends over time
operationId: getCrowdDensity
tags:
- Analytics
parameters:
- name: order_id
in: path
required: true
schema:
type: string
responses:
'200':
description: Crowd density data
content:
application/json:
schema:
type: object
properties:
location_id:
type: string
location_name:
type: string
measurements:
type: array
items:
type: object
properties:
date:
type: string
format: date
density_level:
type: string
enum: [empty, low, moderate, high, very_high]
estimated_count:
type: integer
confidence:
type: number
minimum: 0
maximum: 1
/analytics/orders/{order_id}/sentiment:
get:
summary: Sentiment analysis
description: Analyze emotional tone and engagement from photos
operationId: getSentiment
tags:
- Analytics
parameters:
- name: order_id
in: path
required: true
schema:
type: string
responses:
'200':
description: Sentiment analysis results
content:
application/json:
schema:
type: object
properties:
overall_mood:
type: string
enum: [very_negative, negative, neutral, positive, very_positive]
engagement_level:
type: string
enum: [low, moderate, high]
atmosphere:
type: string
trends:
type: array
items:
type: object
properties:
date:
type: string
format: date
mood_score:
type: number
minimum: 0
maximum: 1
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: API key
description: |
Your quiXzoom API key. Get one at https://www.quixzoom.com/developers
Example: `Authorization: Bearer qz_live_abc123...`
schemas:
OrderRequest:
type: object
required:
- category
- locations
properties:
client_reference:
type: string
description: Your internal reference ID
example: "malmo-museums-2026"
category:
type: string
description: Photo category
enum:
- cultural_exterior
- cultural_interior
- restaurant_ambiance
- retail_compliance
- event_venue_status
- beach_facility_status
- park_recreation
- infrastructure_condition
- custom
description:
type: string
description: Detailed description of what you need
example: "Exterior photos of all museums in Malmö municipality"
locations:
type: array
minItems: 1
maxItems: 1000
items:
$ref: '#/components/schemas/Location'
requirements:
$ref: '#/components/schemas/PhotoRequirements'
delivery:
$ref: '#/components/schemas/DeliveryConfig'
recurring:
$ref: '#/components/schemas/RecurringConfig'
budget:
$ref: '#/components/schemas/BudgetConfig'
timeline:
$ref: '#/components/schemas/TimelineConfig'
Location:
type: object
required:
- coordinates
properties:
location_id:
type: string
description: Your internal location ID
name:
type: string
description: Human-readable location name
example: "Malmö Konstmuseum"
address:
type: string
example: "S:t Johannesgatan 7, 211 46 Malmö"
coordinates:
type: object
required:
- lat
- lng
properties:
lat:
type: number
minimum: -90
maximum: 90
example: 55.6050
lng:
type: number
minimum: -180
maximum: 180
example: 13.0038
requirements:
$ref: '#/components/schemas/PhotoRequirements'
PhotoRequirements:
type: object
properties:
angles:
type: array
items:
type: string
enum: [front, back, side, entrance, interior, overview, detail, custom]
example: ["front", "entrance"]
minimum_resolution:
type: string
pattern: '^\d+x\d+$'
example: "1920x1080"
time_of_day:
type: string
enum: [dawn, morning, midday, afternoon, evening, night, any]
weather:
type: string
enum: [sunny, cloudy, any]
avoid:
type: array
items:
type: string
example: ["construction scaffolding", "closed shutters"]
brand_match:
type: string
description: Verify specific brand/logo is visible
example: "ICA"
minimum_crowd:
type: string
enum: [empty, low, moderate, high, any]
description: Minimum crowd level for ambiance shots
DeliveryConfig:
type: object
properties:
format:
type: string
enum: [structured_json, raw_urls, zip_archive]
default: structured_json
include_metadata:
type: boolean
default: true
include_ai_analysis:
type: boolean
default: false
webhook_url:
type: string
format: uri
description: URL to receive webhook events
RecurringConfig:
type: object
properties:
enabled:
type: boolean
default: false
frequency:
type: string
enum: [daily, weekly, bi_weekly, monthly, quarterly]
day_of_week:
type: integer
minimum: 1
maximum: 7
description: For weekly frequency (1=Monday)
day_of_month:
type: integer
minimum: 1
maximum: 31
time_window:
type: string
pattern: '^\d{2}:\d{2}-\d{2}:\d{2}$'
example: "09:00-17:00"
seasonal_adjustments:
type: boolean
default: false
season:
type: string
enum: [year_round, summer_only, winter_only]
notify_before_capture:
type: integer
description: Hours before capture to notify
example: 24
pause_conditions:
type: object
properties:
weather_extreme:
type: boolean
holiday_override:
type: array
items:
type: string
format: date
BudgetConfig:
type: object
properties:
max_total:
type: number
minimum: 0
currency:
type: string
default: USD
per_photo_max:
type: number
minimum: 0
TimelineConfig:
type: object
properties:
desired_completion:
type: string
format: date-time
flexible:
type: boolean
default: false
OrderResponse:
type: object
properties:
order_id:
type: string
example: "ord_7f8a9b2c"
status:
type: string
enum: [accepted, pending_confirmation]
estimated_price:
$ref: '#/components/schemas/PriceEstimate'
estimated_completion:
type: string
format: date-time
missions_created:
type: integer
webhook_secret:
type: string
confirmation_url:
type: string
format: uri
PriceEstimate:
type: object
properties:
total:
type: number
example: 2840.00
currency:
type: string
example: "USD"
breakdown:
type: object
properties:
base_mission_fee:
type: number
per_location:
type: number
ai_verification:
type: number
recurring_discount:
type: number
OrderSummary:
type: object
properties:
order_id:
type: string
client_reference:
type: string
status:
type: string
category:
type: string
created_at:
type: string
format: date-time
total_locations:
type: integer
photos_delivered:
type: integer
recurring:
type: boolean
OrderDetail:
allOf:
- $ref: '#/components/schemas/OrderSummary'
- type: object
properties:
progress:
type: object
properties:
total_missions:
type: integer
completed:
type: integer
in_progress:
type: integer
pending:
type: integer
failed:
type: integer
photos_delivered:
type: integer
photos_pending:
type: integer
next_recurring_date:
type: string
format: date-time
total_spent:
type: number
budget_remaining:
type: number
locations:
type: array
items:
$ref: '#/components/schemas/Location'
OrderUpdate:
type: object
properties:
locations:
type: array
items:
$ref: '#/components/schemas/Location'
requirements:
$ref: '#/components/schemas/PhotoRequirements'
recurring:
$ref: '#/components/schemas/RecurringConfig'
webhook_url:
type: string
format: uri
status:
type: string
enum: [paused, active]
MissionDetail:
type: object
properties:
mission_id:
type: string
order_id:
type: string
status:
type: string
enum: [pending, assigned, in_progress, completed, failed, cancelled]
location:
$ref: '#/components/schemas/Location'
zoomer:
type: object
properties:
zoomer_id:
type: string
rating:
type: number
missions_completed:
type: integer
timeline:
type: object
properties:
assigned_at:
type: string
format: date-time
completed_at:
type: string
format: date-time
verified_at:
type: string
format: date-time
photos:
type: array
items:
$ref: '#/components/schemas/Photo'
Photo:
type: object
properties:
photo_id:
type: string
url:
type: string
format: uri
thumbnail:
type: string
format: uri
angle:
type: string
resolution:
type: string
file_size_mb:
type: number
format:
type: string
metadata:
type: object
properties:
captured_at:
type: string
format: date-time
gps:
type: object
properties:
lat:
type: number
lng:
type: number
accuracy_m:
type: number
device:
type: string
weather:
type: object
properties:
condition:
type: string
temp_c:
type: number
verification:
type: object
properties:
status:
type: string
enum: [pending, approved, rejected]
ai_checks:
type: object
additionalProperties:
type: object
properties:
score:
type: number
passed:
type: boolean
reviewed_by:
type: string
nullable: true
ai_analysis:
type: object
properties:
amos_vision:
type: object
properties:
object_detection:
type: array
items:
type: string
scene_classification:
type: string
condition_assessment:
type: string
amos_change:
type: object
properties:
changes_since_last:
type: array
items:
type: string
change_confidence:
type: number
amos_risk:
type: object
properties:
safety_score:
type: number
accessibility_score:
type: number
maintenance_urgency:
type: string
amos_sentiment:
type: object
properties:
crowd_mood:
type: string
engagement_level:
type: string
atmosphere:
type: string
ChangeDetectionResult:
type: object
properties:
comparison_period:
type: string
changes_detected:
type: array
items:
type: object
properties:
location_id:
type: string
location_name:
type: string
change_type:
type: string
enum: [new_construction, renovation, seasonal_variation, damage, new_signage, removed_object, crowd_change, other]
confidence:
type: number
description:
type: string
photos:
type: object
properties:
before:
type: string
after:
type: string
Error:
type: object
properties:
error:
type: object
properties:
code:
type: string
message:
type: string
details:
type: object
suggested_action:
type: string
+723
View File
@@ -0,0 +1,723 @@
# quiXzoom Developer API — Product Specification
> **Version:** 1.0.0
> **Status:** Draft
> **Last updated:** 2026-07-14
> **Owner:** Landvex Inc / quiXzoom Platform Team
---
## Executive Summary
quiXzoom Developer API enables software developers, agencies, and platform builders to programmatically order, verify, and retrieve real-world geotagged photography. Unlike stock photo APIs that serve stale archives, quiXzoom dispatches verified field contributors ("Zoomers") to capture fresh visual data on demand.
**The core value proposition:** Any visual information gap in a digital product can be filled with fresh, verified, structured photography — ordered via REST API and delivered within hours.
---
## The Problem We Solve
### Scenario: Malmö Stad Website Redesign
A marketing agency wins a contract to rebuild Malmö Stad's tourism website. The design mockups need real photography of:
- All 15 museums (exterior + current exhibitions)
- 40 public parks (seasonal conditions, crowd levels)
- 8 beaches (water quality flags, facility status)
- 25 restaurants in the old town (ambiance, outdoor seating)
**Traditional approach:**
1. City sends archive photos from 2019 (outdated, wrong seasons)
2. Agency hires a media crew for 3 days (€8,000+, scheduling hell)
3. Photos are staged, not representative of actual conditions
4. Website launches with stale visuals, requires redo in 6 months
**quiXzoom approach:**
```bash
# Order all museum exteriors — fresh, current, verified
POST /v1/missions
{
"category": "cultural_exterior",
"locations": [...15 museum coordinates...],
"requirements": {
"angles": ["front", "entrance_signage"],
"time_of_day": "daylight",
"weather": "any"
},
"delivery_format": "api_json",
"recurring": {
"frequency": "monthly",
"seasonal_adjustments": true
}
}
# Response: mission_id, estimated_completion, price_quote
# Poll for completion
GET /v1/missions/{mission_id}/status
# → "completed" — photos ready
# Retrieve structured data
GET /v1/missions/{mission_id}/photos
# → JSON with URLs, metadata, verification_status, AI_analysis
```
**Result:** €200, 4-hour turnaround, photos verified by AI against requirements, auto-updating every month.
---
## Product Architecture
```
┌─────────────────────────────────────────────────────────────────────────┐
│ DEVELOPER APPLICATION │
│ (Website, App, Dashboard, CMS, Digital Signage, AI Training Pipeline) │
└─────────────────────────────────────────────────────────────────────────┘
▼ REST API
┌─────────────────────────────────────────────────────────────────────────┐
│ quiXzoom DEVELOPER API │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Orders │ │ Missions │ │ Photos │ │ Analytics │ │
│ │ /orders │ │ /missions │ │ /photos │ │ /analytics │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
┌───────────────┼───────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Order │ │ Order │ │ Order │
│ Routing │ │ Matching │ │ Pricing │
│ Engine │ │ Engine │ │ Engine │
└──────────┘ └──────────┘ └──────────┘
│ │ │
└───────────────┼───────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ ZOOMER NETWORK │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Zoomer │ │ Zoomer │ │ Zoomer │ │ Zoomer │ │ Zoomer │ ... │
│ │ #4721 │ │ #4722 │ │ #4723 │ │ #4724 │ │ #4725 │ │
│ │ Malmö │ │ Göteborg│ │ Stockholm││ Uppsala│ │ Lund │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
┌───────────────┼───────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Photo │ │ GPS │ │ Quality │
│ Capture │ │ Verify │ │ Verify │
└──────────┘ └──────────┘ └──────────┘
│ │ │
└───────────────┼───────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ AI VERIFICATION PIPELINE │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Object │ │ Angle │ │ Condition │ │ Geo │ │
│ │ Detection │ │ Match │ │ Check │ │ Validate │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Crowd │ │ Weather │ │ Time │ │ Brand │ │
│ │ Density │ │ Detect │ │ Verify │ │ Match │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ DELIVERY & ANALYTICS │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Raw Photo │ │ Metadata │ │ Landvex │ │ Change │ │
│ │ CDN │ │ JSON │ │ Analysis │ │ Detection │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
```
---
## API Endpoints (v1)
### 1. Orders — Create and manage photo orders
#### `POST /v1/orders`
Create a new photo order.
**Request:**
```json
{
"order_id": "ord_7f8a9b2c",
"client_reference": "malmo-stad-v2-2026",
"category": "cultural_exterior",
"description": "Exterior photos of all museums in Malmö municipality. Front facade + entrance signage. Daylight, any weather.",
"locations": [
{
"location_id": "loc_001",
"name": "Malmö Konstmuseum",
"address": "S:t Johannesgatan 7, 211 46 Malmö",
"coordinates": {"lat": 55.6050, "lng": 13.0038},
"requirements": {
"angles": ["front", "entrance"],
"minimum_resolution": "1920x1080",
"time_of_day": "daylight",
"avoid": ["construction scaffolding", "closed shutters"]
}
}
],
"delivery": {
"format": "structured_json",
"include_metadata": true,
"include_ai_analysis": true,
"webhook_url": "https://api.malmocity.se/quixzoom/webhook"
},
"recurring": {
"enabled": true,
"frequency": "monthly",
"seasonal_adjustments": true,
"notify_before_capture": 24
},
"budget": {
"max_total": 5000.00,
"currency": "USD",
"per_photo_max": 5.00
},
"timeline": {
"desired_completion": "2026-07-20T23:59:59Z",
"flexible": false
}
}
```
**Response:**
```json
{
"order_id": "ord_7f8a9b2c",
"status": "accepted",
"estimated_price": {
"total": 2840.00,
"currency": "USD",
"breakdown": {
"base_mission_fee": 15.00,
"per_location": 8.00,
"ai_verification": 2.00,
"recurring_discount": -0.10
}
},
"estimated_completion": "2026-07-18T14:00:00Z",
"missions_created": 15,
"webhook_secret": "whsec_...",
"confirmation_url": "https://api.quixzoom.com/v1/orders/ord_7f8a9b2c/confirm"
}
```
---
#### `GET /v1/orders/{order_id}`
Retrieve order status and details.
**Response:**
```json
{
"order_id": "ord_7f8a9b2c",
"status": "in_progress",
"progress": {
"total_missions": 15,
"completed": 7,
"in_progress": 5,
"pending": 3,
"failed": 0
},
"photos_delivered": 42,
"photos_pending": 18,
"next_recurring_date": "2026-08-14T00:00:00Z",
"total_spent": 1320.00,
"budget_remaining": 1680.00
}
```
---
#### `PATCH /v1/orders/{order_id}`
Modify an active order (add locations, change requirements, pause recurring).
---
#### `DELETE /v1/orders/{order_id}`
Cancel an order and stop any recurring missions.
---
### 2. Missions — Individual photo capture tasks
#### `GET /v1/missions/{mission_id}`
Get mission details and current status.
**Response:**
```json
{
"mission_id": "mis_a3b4c5d6",
"order_id": "ord_7f8a9b2c",
"status": "completed",
"location": {
"name": "Malmö Konstmuseum",
"coordinates": {"lat": 55.6050, "lng": 13.0038}
},
"zoomer": {
"zoomer_id": "zmr_4721",
"rating": 4.8,
"missions_completed": 342
},
"timeline": {
"assigned_at": "2026-07-15T09:23:00Z",
"completed_at": "2026-07-15T11:45:00Z",
"verified_at": "2026-07-15T12:03:00Z"
},
"photos": [
{
"photo_id": "img_x7y8z9",
"url": "https://cdn.quixzoom.com/v1/photos/img_x7y8z9.jpg",
"thumbnail": "https://cdn.quixzoom.com/v1/photos/img_x7y8z9_thumb.jpg",
"angle": "front",
"resolution": "4032x3024",
"file_size_mb": 4.2,
"format": "jpeg",
"metadata": {
"captured_at": "2026-07-15T11:42:18Z",
"gps": {"lat": 55.6051, "lng": 13.0039, "accuracy_m": 3.2},
"device": "iPhone15,2",
"weather": {"condition": "partly_cloudy", "temp_c": 22}
},
"verification": {
"status": "approved",
"ai_checks": {
"location_match": {"score": 0.98, "passed": true},
"angle_match": {"score": 0.94, "passed": true},
"quality_check": {"score": 0.91, "passed": true},
"obstruction_check": {"score": 0.99, "passed": true}
},
"reviewed_by": null
}
}
]
}
```
---
### 3. Photos — Retrieve and manage delivered photos
#### `GET /v1/photos/{photo_id}`
Get photo metadata and URLs.
#### `GET /v1/photos?order_id={order_id}&angle=front&status=approved`
List photos with filtering.
#### `GET /v1/photos/{photo_id}/download`
Download original resolution photo (signed URL, expires in 1 hour).
---
### 4. Analytics — Insights from photo data
#### `GET /v1/analytics/orders/{order_id}/changes`
Detect changes between photo sets (for recurring missions).
**Response:**
```json
{
"comparison_period": "2026-06-15 to 2026-07-15",
"changes_detected": [
{
"location_id": "loc_003",
"location_name": "Teknikens och Sjöfartens Hus",
"change_type": "new_construction",
"confidence": 0.87,
"description": "Scaffolding erected on east facade. Entrance temporarily relocated.",
"photos": {
"before": "img_abc123",
"after": "img_def456"
}
},
{
"location_id": "loc_007",
"location_name": "Moderna Museet Malmö",
"change_type": "seasonal_variation",
"confidence": 0.95,
"description": "Outdoor exhibition space now active. 23 visitors visible (vs 0 in June).",
"photos": {
"before": "img_ghi789",
"after": "img_jkl012"
}
}
]
}
```
---
#### `GET /v1/analytics/orders/{order_id}/crowd-density`
Crowd density analysis over time.
#### `GET /v1/analytics/orders/{order_id}/sentiment`
Emotional/sentiment analysis from facial expressions and body language.
---
## AI Verification Pipeline
Every photo passes through multi-layer AI verification before delivery:
| Check | Description | Threshold |
|-------|-------------|-----------|
| **Location Match** | GPS coordinates within 50m of target | ≥ 95% |
| **Angle Match** | Photo angle matches requirement (front/side/etc) | ≥ 90% |
| **Quality Check** | Resolution, blur, exposure, noise | ≥ 85% |
| **Obstruction Check** | No major obstructions (vehicles, scaffolding) | ≥ 95% |
| **Object Detection** | Required objects present (signage, building) | ≥ 90% |
| **Time Verify** | Photo taken within requested time window | ≥ 99% |
| **Weather Detect** | Actual weather conditions logged | Always |
| **Brand Match** | Logo/signage matches reference (if specified) | ≥ 85% |
**Failed verification flow:**
1. Photo fails one or more checks
2. Zoomer notified with specific failure reason
3. Zoomer can retake within 2 hours (no extra charge)
4. If still failing, mission reassigned to new Zoomer
5. Client notified of delay with new ETA
---
## Recurring Missions
### Configuration
```json
{
"recurring": {
"enabled": true,
"frequency": "monthly",
"day_of_month": 15,
"seasonal_adjustments": true,
"notify_before_capture": 24,
"pause_conditions": {
"weather_extreme": true,
"holiday_override": ["2026-12-25", "2026-12-26"]
}
}
}
```
### Seasonal Adjustments
| Season | Adjustment | Example |
|--------|-----------|---------|
| Spring | Earlier capture time | Parks photographed at 10:00 (flowers blooming) |
| Summer | Extended hours | Beach photos at 18:00 (peak activity) |
| Autumn | Weather contingency | Indoor fallback for rain-sensitive locations |
| Winter | Reduced frequency | Monthly → Bi-monthly for outdoor venues |
---
## Use Cases & Examples
### 1. Municipal Website (Malmö Stad)
```javascript
// Initialize client
const quixzoom = new QuixzoomClient({
apiKey: process.env.QUIXZOOM_API_KEY,
environment: 'production'
});
// Order all museum exteriors — monthly refresh
const order = await quixzoom.orders.create({
client_reference: 'malmo-museums-2026',
category: 'cultural_exterior',
locations: museums.map(m => ({
name: m.name,
coordinates: m.coordinates,
requirements: {
angles: ['front', 'entrance'],
avoid: ['construction']
}
})),
recurring: {
frequency: 'monthly',
seasonal_adjustments: true
},
delivery: {
webhook_url: 'https://api.malmocity.se/photos/update'
}
});
// Webhook receives:
{
event: 'photos.delivered',
order_id: 'ord_7f8a9b2c',
mission_id: 'mis_a3b4c5d6',
photos: [{
url: 'https://cdn.quixzoom.com/...',
metadata: { ... },
ai_analysis: {
crowd_density: 'low',
weather: 'sunny',
condition: 'well_maintained'
}
}]
}
```
---
### 2. Restaurant Discovery App
```python
# Python SDK example
from quixzoom import QuixzoomClient
client = QuixzoomClient(api_key="qz_live_...")
# Weekly ambiance updates for trending restaurants
order = client.orders.create(
category="restaurant_ambiance",
locations=[
{"name": "Lilla Kafferosteriet", "coordinates": (55.605, 13.0038)},
{"name": "Bullen", "coordinates": (55.603, 13.001)}
],
requirements={
"angles": ["interior", "outdoor_seating", "bar_area"],
"time_of_day": "evening",
"minimum_crowd": "moderate" # Capture real vibe
},
recurring={
"frequency": "weekly",
"day_of_week": "friday",
"time_window": "18:00-21:00"
}
)
# Use crowd density + sentiment for "vibe score"
for photo in order.photos:
vibe_score = (
photo.ai_analysis.crowd_density * 0.4 +
photo.ai_analysis.sentiment_positive * 0.3 +
photo.ai_analysis.ambiance_lighting * 0.3
)
update_restaurant_vibe(photo.location_id, vibe_score)
```
---
### 3. Event Venue Monitoring
```bash
# Real-time venue status for event planners
curl -X POST https://api.quixzoom.com/v1/orders \
-H "Authorization: Bearer $QUIXZOOM_API_KEY" \
-d '{
"category": "event_venue_status",
"locations": [
{"name": "Malmö Arena", "coordinates": {"lat": 55.563, "lng": 12.976}}
],
"requirements": {
"angles": ["entrance_queue", "parking_lot", "main_entrance"],
"time_of_day": "evening",
"recurring": {
"frequency": "daily",
"time_window": "19:00-23:00",
"event_nights_only": true
}
}
}'
# Returns real-time crowd estimates for app users:
# "Malmö Arena: Moderate crowd (450 people), 5 min queue, parking 80% full"
```
---
### 4. Retail Chain Compliance
```javascript
// Monthly storefront audits for franchise compliance
const order = await quixzoom.orders.create({
client_reference: 'ica-stores-july-2026',
category: 'retail_compliance',
locations: icaStores.map(store => ({
name: store.name,
coordinates: store.coordinates,
requirements: {
angles: ['storefront', 'opening_hours_sign', 'promotional_display'],
brand_match: 'ICA', // AI verifies ICA logo present
obstruction_check: true
}
})),
recurring: {
frequency: 'monthly',
deliver_before: '5th of month' // For management reports
}
});
// Automated compliance report:
// - Store #234: Compliant ✓
// - Store #235: Non-compliant ✗ (promotional display missing)
// - Store #236: Non-compliant ✗ (opening hours sign obscured)
```
---
### 5. Beach & Outdoor Facility Status
```python
# Daily beach status for summer season
order = client.orders.create(
category="beach_facility_status",
locations=malmo_beaches,
requirements={
"angles": ["overview", "water_quality_flag", "lifeguard_tower", "facilities"],
"time_of_day": "midday"
},
recurring={
"frequency": "daily",
"season": "summer_only", # June 1 - August 31
"weather_dependent": True # Skip if thunderstorm
}
)
# AI analysis delivers:
# - Water quality flag color (blue/yellow/red)
# - Crowd density estimate
# - Lifeguard presence (yes/no)
# - Facility condition (clean/moderate/poor)
```
---
## Integration with Landvex Intelligence
When `include_ai_analysis: true` is set, photos are automatically processed through Landvex AI engines:
```json
{
"ai_analysis": {
"amos_vision": {
"object_detection": ["building", "signage", "people", "vehicles"],
"scene_classification": "urban_cultural",
"condition_assessment": "well_maintained"
},
"amos_change": {
"changes_since_last": ["new_banner", "repainted_facade"],
"change_confidence": 0.89
},
"amos_risk": {
"safety_score": 0.94,
"accessibility_score": 0.87,
"maintenance_urgency": "low"
},
"amos_sentiment": {
"crowd_mood": "positive",
"engagement_level": "moderate",
"atmosphere": "welcoming"
}
}
}
```
---
## Pricing
| Tier | Volume | Per Photo | Features |
|------|--------|-----------|----------|
| **Developer** | 0-1,000 photos/month | $3.00 | API access, basic verification, 48h delivery |
| **Business** | 1,000-10,000 photos/month | $2.00 | Priority delivery, advanced AI analysis, webhooks |
| **Enterprise** | 10,000+ photos/month | Custom | SLA guarantees, dedicated support, custom AI models |
**Recurring mission discount:** 10% off for monthly, 15% for weekly.
---
## SDKs & Libraries
| Language | Package | Status |
|----------|---------|--------|
| JavaScript/TypeScript | `@quixzoom/sdk` | Available |
| Python | `quixzoom-python` | Available |
| Go | `github.com/quixzoom/go-sdk` | Beta |
| Ruby | `quixzoom-ruby` | Coming Q3 2026 |
| PHP | `quixzoom-php` | Coming Q3 2026 |
---
## Webhooks
Events delivered to your endpoint:
| Event | Description |
|-------|-------------|
| `order.created` | Order accepted and priced |
| `order.confirmed` | Payment received, missions dispatched |
| `mission.assigned` | Zoomer assigned to location |
| `mission.completed` | Photos captured, pending verification |
| `photos.verified` | AI verification passed |
| `photos.delivered` | Photos ready for download |
| `photos.rejected` | Verification failed, being retaken |
| `order.completed` | All missions complete |
| `recurring.triggered` | New recurring cycle started |
---
## Error Handling
```json
{
"error": {
"code": "location_unserviceable",
"message": "No Zoomers available within 50km of specified coordinates",
"details": {
"coordinates": {"lat": 67.8558, "lng": 20.2253},
"nearest_zoomer": {"distance_km": 127, "location": "Luleå"}
},
"suggested_action": "Increase budget for remote area surcharge or choose 'flexible' timeline"
}
}
```
---
## Rate Limits
| Tier | Requests/minute | Concurrent orders |
|------|-----------------|-------------------|
| Developer | 60 | 5 |
| Business | 300 | 25 |
| Enterprise | 2000 | Unlimited |
---
## Security
- All API requests require `Authorization: Bearer {api_key}`
- Webhook signatures verified with HMAC-SHA256
- Photo URLs are signed and expire after 1 hour
- GDPR compliant — all photos include consent metadata
- SOC 2 Type II certified infrastructure
---
## Support
- **Documentation:** https://docs.quixzoom.com
- **API Status:** https://status.quixzoom.com
- **Support Email:** dev-support@quixzoom.com
- **Slack Community:** https://quixzoom.dev/slack
---
## Changelog
| Version | Date | Changes |
|---------|------|---------|
| 1.0.0 | 2026-07-14 | Initial release — Orders, Missions, Photos, Analytics endpoints |
---
*quiXzoom Developer API is a product of Landvex Inc. All rights reserved.*