Read live capabilities
Returns supported verticals, job type IDs, required fields, geographic scope, and non-bookable future verticals.
Aune API
Search provider, fixed-price, and slot combinations with postcodes but without street address or customer contact data. Confirm the exact option only after user choice, consent, and terms acceptance. Fall back to provider follow-up when no option exists.
Returns supported verticals, job type IDs, required fields, geographic scope, and non-bookable future verticals.
Checks current provider eligibility, provider-owned fixed price, and concrete slots. Returns short-lived option IDs and exact terms versions.
Revalidates provider, price, slot, consent, terms, and idempotency before creating a durable confirmed booking and calendar entry.
Returns redacted provider, slot, price, terms version, and confirmation status without customer contact PII.
Creates a structured request after consent when no direct option exists. This endpoint does not confirm provider, availability, slot, booking, or final price.
Quickstart
Capabilities define the current taxonomy. Booking search then checks real provider price and slot supply without customer contact details.
curl "$AUNE_BASE_URL/api/public/requests/capabilities"curl -X POST "$AUNE_BASE_URL/api/public/booking-options" \
-H "Content-Type: application/json" \
--data '{
"spec_version": "public_bookings_api_v1",
"vertical_id": "moving",
"job_type_id": "moving_home",
"description": "Home move tomorrow afternoon from postcode 111 20 to 118 20. The apartment is 45 sqm with about 25 boxes, a sofa, and a bed. Both addresses have elevators.",
"location": {
"country_code": "SE",
"postcode": "111 20",
"city": "Stockholm"
},
"destination_location": {
"country_code": "SE",
"postcode": "118 20",
"city": "Stockholm"
},
"timing": {
"preferred_time_text": "Tomorrow afternoon"
},
"details": {
"home_size_sqm": 45,
"boxes": 25,
"elevator_origin": true,
"elevator_destination": true
},
"locale": "sv-SE",
"timezone": "Europe/Stockholm"
}'curl -X POST "$AUNE_BASE_URL/api/public/requests" \
-H "Authorization: Bearer $AUNE_PUBLIC_REQUESTS_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: partner-case-123" \
--data '{
"spec_version": "public_requests_api_v1",
"vertical_id": "vvs",
"job_type_id": "leak_faucet_fixture",
"description": "Kitchen faucet leaks when used. Customer wants help next week.",
"user_consent_confirmed": true,
"user_consent_statement": "The customer agreed that Aune may receive their contact details and request details for provider follow-up.",
"consent_source": "external_model_conversation",
"customer": {
"name": "Anna Andersson",
"phone": "0701234567",
"email": "anna@example.se"
},
"location": {
"input": "Storgatan 12, 118 61 Stockholm"
},
"timing": {
"preferred_time_text": "Next Friday morning"
},
"budget_sek": 4500,
"details": {
"fixture": "kitchen faucet"
},
"source": "external_model",
"external_reference": "partner-case-123",
"idempotency_key": "partner-case-123",
"locale": "sv-SE",
"timezone": "Europe/Stockholm"
}'Examples
Both surfaces use postcode-only search followed by an authenticated confirmation carrying the unchanged option, consent evidence, exact terms version, and idempotency key.
const baseUrl = process.env.AUNE_BASE_URL ?? "https://aune-homepage-chat.vercel.app";
const search = await fetch(`${baseUrl}/api/public/booking-options`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
"spec_version": "public_bookings_api_v1",
"vertical_id": "moving",
"job_type_id": "moving_home",
"description": "Home move tomorrow afternoon from postcode 111 20 to 118 20. The apartment is 45 sqm with about 25 boxes, a sofa, and a bed. Both addresses have elevators.",
"location": {
"country_code": "SE",
"postcode": "111 20",
"city": "Stockholm"
},
"destination_location": {
"country_code": "SE",
"postcode": "118 20",
"city": "Stockholm"
},
"timing": {
"preferred_time_text": "Tomorrow afternoon"
},
"details": {
"home_size_sqm": 45,
"boxes": 25,
"elevator_origin": true,
"elevator_destination": true
},
"locale": "sv-SE",
"timezone": "Europe/Stockholm"
}),
}).then((response) => response.json());
if (!search.direct_booking_available) {
console.log(search.fallback);
process.exit(0);
}
const option = search.options[0]; // Present options and let the user choose.
const response = await fetch(`${baseUrl}/api/public/bookings`, {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.AUNE_PUBLIC_REQUESTS_API_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
spec_version: "public_bookings_api_v1",
booking_option_id: option.booking_option_id,
customer: {
name: "Anna Andersson",
phone: "0701234567",
email: "anna@example.se",
},
service_location: {
country_code: "SE",
address: "Storgatan 12",
postcode: "111 20",
},
destination_location: {
country_code: "SE",
address: "Hornsgatan 20",
postcode: "118 20",
},
user_consent_confirmed: true,
booking_terms_accepted: true,
booking_terms_version: option.terms.version,
booking_terms_accepted_at: new Date().toISOString(),
idempotency_key: "conversation-123-option-1",
}),
});
const result = await response.json();import json
import os
import requests
base_url = os.getenv("AUNE_BASE_URL", "https://aune-homepage-chat.vercel.app")
token = os.environ["AUNE_PUBLIC_REQUESTS_API_TOKEN"]
search_payload = json.loads(r'''{
"spec_version": "public_bookings_api_v1",
"vertical_id": "moving",
"job_type_id": "moving_home",
"description": "Home move tomorrow afternoon from postcode 111 20 to 118 20. The apartment is 45 sqm with about 25 boxes, a sofa, and a bed. Both addresses have elevators.",
"location": {
"country_code": "SE",
"postcode": "111 20",
"city": "Stockholm"
},
"destination_location": {
"country_code": "SE",
"postcode": "118 20",
"city": "Stockholm"
},
"timing": {
"preferred_time_text": "Tomorrow afternoon"
},
"details": {
"home_size_sqm": 45,
"boxes": 25,
"elevator_origin": true,
"elevator_destination": true
},
"locale": "sv-SE",
"timezone": "Europe/Stockholm"
}''')
search = requests.post(
f"{base_url}/api/public/booking-options",
json=search_payload,
timeout=20,
).json()
if not search["direct_booking_available"]:
print(search["fallback"])
raise SystemExit(0)
option = search["options"][0] # Present options and let the user choose.
payload = {
"spec_version": "public_bookings_api_v1",
"booking_option_id": option["booking_option_id"],
"customer": {
"name": "Anna Andersson",
"phone": "0701234567",
"email": "anna@example.se",
},
"service_location": {
"country_code": "SE",
"address": "Storgatan 12",
"postcode": "111 20",
},
"destination_location": {
"country_code": "SE",
"address": "Hornsgatan 20",
"postcode": "118 20",
},
"user_consent_confirmed": True,
"booking_terms_accepted": True,
"booking_terms_version": option["terms"]["version"],
"booking_terms_accepted_at": "2026-07-10T10:00:00.000Z",
"idempotency_key": "conversation-123-option-1",
}
response = requests.post(
f"{base_url}/api/public/bookings",
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
},
json=payload,
timeout=20,
)
response.raise_for_status()
print(response.json()){
"spec_version": "public_requests_api_v1",
"vertical_id": "cleaning",
"job_type_id": "cleaning_move_out",
"description": "Move-out cleaning for an empty 82 sqm apartment next Friday.",
"user_consent_confirmed": true,
"user_consent_statement": "The customer agreed that Aune may receive their contact details and request details for provider follow-up.",
"consent_source": "external_model_conversation",
"customer": {
"name": "Anna Andersson",
"phone": "0701234567",
"email": "anna@example.se"
},
"location": {
"input": "Storgatan 12, 118 61 Stockholm"
},
"timing": {
"preferred_time_text": "Next Friday morning"
},
"details": {
"square_meters": 82,
"move_state": "empty"
},
"source": "external_model",
"external_reference": "partner-cleaning-123",
"idempotency_key": "partner-cleaning-123",
"locale": "sv-SE",
"timezone": "Europe/Stockholm"
}Responses
A booking exists only when all three truth flags are true and `booking.status` is `confirmed`. Notification delivery is reported separately and never defines whether the booking exists.
{
"ok": true,
"spec_version": "public_bookings_api_v1",
"request_id": "nvr_booking_...",
"booking": {
"id": "network_...",
"status": "confirmed",
"provider_name": "Example Moving AB",
"service_id": "moving_home_starter_3h",
"slot_start_at": "2026-07-11T13:00:00.000Z",
"slot_end_at": "2026-07-11T16:00:00.000Z",
"price_sek": 2800,
"currency": "SEK",
"terms_version": "fixed_price_terms_v1:moving_home_starter_3h"
},
"booking_created": true,
"availability_checked": true,
"provider_selected": true,
"idempotent_replay": false,
"safe_next_step": "Tell the user the booking is confirmed."
}Errors
Invalid payload or missing required fields.
Missing or invalid API token.
Unsupported vertical or job_type_id for the selected vertical.
Rate limit exceeded.
Production token is not configured.