> ## Documentation Index
> Fetch the complete documentation index at: https://docs.avoca.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# API & Integration Methods

> Endpoint design, authentication, and REST standards for the custom integration

# API and Integration Methods

<Note>
  This page is a **recommended specification for the API your team exposes to Avoca** — not documentation of existing Avoca endpoints. Production custom integrations today use the [two-step payload handshake pattern](/custom-integration/payload-handshake); a standard REST design like the one below is equally supported for new integrations. Endpoint paths, field names, and shapes are adapted to your system during the integration process.
</Note>

### Recommended API Endpoints

**Availability Management**

```http theme={null}
GET /api/v1/availability
```

Purpose: Query available appointment slots\
Required parameters:

* `service_type` (string)
* `location_id` (string)
* `date_range_start` (ISO 8601 datetime)
* `date_range_end` (ISO 8601 datetime)
* `provider_id` (string, optional)
* `duration_minutes` (integer, optional)

Sample request:

```json theme={null}
{
  "service_type": "inspection",
  "location_id": "LOC-12345",
  "date_range_start": "2025-11-01T08:00:00Z",
  "date_range_end": "2025-11-07T18:00:00Z",
  "duration_minutes": 60
}
```

Expected response:

```json theme={null}
{
  "available_slots": [
    {
      "slot_id": "SLOT-789",
      "start_time": "2025-11-01T09:00:00Z",
      "end_time": "2025-11-01T10:00:00Z",
      "provider_id": "PROV-456",
      "provider_name": "John Smith",
      "price": 150.0,
      "currency": "USD"
    }
  ],
  "total_slots": 15,
  "next_available": "2025-11-01T09:00:00Z"
}
```

**Booking Creation**

```http theme={null}
POST /api/v1/bookings
```

Purpose: Create new appointment booking\
Required fields:

* `slot_id` (string)
* `customer` (object) – `name`, `email`, `phone`, and optional `address`
* `service_type` (string)
* `notes` (string, optional)
* `notification_preferences` (object, optional)

Sample request:

```json theme={null}
{
  "slot_id": "SLOT-789",
  "customer": {
    "name": "Jane Doe",
    "email": "jane.doe@example.com",
    "phone": "+1-555-0123",
    "address": {
      "street": "123 Main St",
      "city": "Springfield",
      "state": "IL",
      "zip": "62701"
    }
  },
  "service_type": "inspection",
  "notes": "Prefer morning appointments",
  "notification_preferences": {
    "sms": true,
    "email": true,
    "reminder_hours_before": 24
  }
}
```

Expected response:

```json theme={null}
{
  "booking_id": "BOOK-12345",
  "confirmation_number": "CONF-ABC123",
  "status": "confirmed",
  "appointment_time": "2025-11-01T09:00:00Z",
  "customer": {},
  "provider": {},
  "created_at": "2025-10-31T14:30:00Z"
}
```

**Booking Modifications**

```http theme={null}
PATCH /api/v1/bookings/{booking_id}      # Update existing booking
PUT /api/v1/bookings/{booking_id}/cancel # Cancel existing booking
GET /api/v1/bookings/{booking_id}        # Retrieve booking details
```

Cancellation payload fields:

* `reason` (string, optional)
* `cancellation_type` (string: `customer_initiated`, `provider_initiated`)

**Customer Management**

```http theme={null}
GET /api/v1/customers/{customer_id}  # Retrieve customer profile/history
POST /api/v1/customers              # Create customer profile
PATCH /api/v1/customers/{customer_id}# Update customer details
```

**Service Catalog**

```http theme={null}
GET /api/v1/services            # Retrieve available services and pricing
GET /api/v1/services/{service_id} # Detailed service information
```

**Pricing Queries**

```http theme={null}
POST /api/v1/pricing/calculate
```

Purpose: Calculate pricing for a specific service configuration\
Required fields:

* `service_type` (string)
* `location_id` (string)
* `modifiers` (array, optional) – add-ons, special requirements

### Integration Protocols & Standards

**Primary Protocol: RESTful APIs**

* Format: JSON (UTF-8 encoding)
* Versioning: URL-based (e.g., `/api/v1/`)
* HTTP methods: Full REST semantics (GET, POST, PATCH, PUT, DELETE)
* Status codes: Standard HTTP status codes with detailed error responses

**Webhook Support (Strongly Recommended)** – Avoca consumes webhooks for real-time event notifications.

Webhook events we should receive:

```
booking.confirmed  – Booking successfully created
booking.updated     – Booking details modified
booking.cancelled   – Booking cancelled
booking.reminder    – Appointment reminder (optional)
availability.changed – Availability slots updated
service.updated      – Service catalog changes
pricing.updated      – Pricing changes
```

Webhook payload format:

```json theme={null}
{
  "event_type": "booking.confirmed",
  "event_id": "evt_12345",
  "timestamp": "2025-10-31T14:30:00Z",
  "data": {
    "booking_id": "BOOK-12345",
    "status": "confirmed"
  }
}
```

Webhook requirements:

* Endpoint: We provide a unique webhook endpoint URL per integration
* Security: HMAC signature verification (preferred) or secret token in header
* Delivery: At-least-once delivery with retry logic
* Response: 200 OK within 5 seconds
* Idempotency: Duplicate webhook deliveries handled via `event_id`

**GraphQL (Optional)** – We can support GraphQL if preferred. It reduces over-fetching, is useful for nested queries, and can coexist with REST endpoints.

### Authentication Methods

**Preferred: OAuth 2.0 Client Credentials Flow**

Implementation details:

* Grant type: `client_credentials`
* Token endpoint: `/oauth/token`
* Token format: JWT (preferred) or opaque tokens
* Token expiration: 1 hour recommended
* Refresh strategy: Automatic refresh before expiration
* Scopes: Role-based (e.g., `bookings:read`, `bookings:write`, `customers:read`)

Request:

```http theme={null}
POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&
client_id={our_client_id}&
client_secret={our_client_secret}&
scope=bookings:read bookings:write availability:read
```

Response:

```json theme={null}
{
  "access_token": "eyJhbGc...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "bookings:read bookings:write availability:read"
}
```

**Alternative: API Keys** – If OAuth is not feasible:

* API keys transmitted via `Authorization: Bearer {api_key}`
* Separate keys for production and sandbox
* Key rotation with grace period
* Rate limiting and monitoring per API key

**JWT Tokens** – If using JWT directly:

* Algorithm: RS256 or ES256 (asymmetric preferred)
* Claims: Include `iss`, `aud`, `exp`, `sub`
* Key management: Public key endpoint for signature verification

**Security Requirements**

* Credentials stored in encrypted secrets management (1Password, AWS Secrets Manager)
* Credentials never logged or exposed in errors
* Automatic credential rotation supported
* Per-environment credentials (development, staging, production)

### API Design Preferences

**Data Formats**

* Primary: JSON with UTF-8 encoding
* Date/time: ISO 8601 (e.g., `2025-10-31T14:30:00Z`)
* Decimal numbers: String representation for currency to avoid floating-point drift

**Versioning Strategy**

* URL-based versioning (e.g., `/api/v1/`)
* Maintain at least one previous major version for backward compatibility
* Deprecation notices: Minimum 90-day notice with `Sunset` HTTP header
* Version negotiation: Current version advertised in response headers

**Rate Limiting**

* Recommended thresholds:
  * Standard operations: 1000 requests/minute per API key
  * Availability queries: 300 requests/minute
  * Bulk operations: 100 requests/minute
* Rate limit headers:

```
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1698765432
```

* 429 responses should include clear retry-after guidance
* Allow reasonable burst capacity (e.g., 2× sustained rate for 10 seconds)

**Pagination**

```http theme={null}
GET /api/v1/bookings?page=2&per_page=50
# or
GET /api/v1/bookings?cursor=eyJpZCI6MTIzfQ&limit=50
```

Sample response:

```json theme={null}
{
  "data": [],
  "pagination": {
    "total": 500,
    "page": 2,
    "per_page": 50,
    "next_cursor": "eyJpZCI6MTczfQ"
  }
}
```

**Error Response Format**

```json theme={null}
{
  "error": {
    "code": "SLOT_UNAVAILABLE",
    "message": "The requested time slot is no longer available",
    "details": {
      "slot_id": "SLOT-789",
      "reason": "booked_by_another_customer"
    },
    "request_id": "req_abc123",
    "timestamp": "2025-10-31T14:30:00Z"
  }
}
```

<hr />
