Skip to main content

Endpoint reference

The Valara public API has 10 endpoints across 4 resource groups. All endpoints are under the /api/v1/ prefix and require an X-API-Key header (see Authentication).

The full machine-readable OpenAPI specification is at:

  • https://valara.cloud/api/openapi.json (primary)
  • https://dash.jacoballenmedia.com/api/openapi.json (legacy alias)

Base URLs

https://valara.cloud/api/v1/             (primary)
https://dash.jacoballenmedia.com/api/v1/ (legacy alias)

Both hosts serve live traffic. See CLAUDE.md rule 10a for the two-domain policy.

Listings (7 endpoints)

The listing lifecycle is the core of the API. A "listing" is what the internal data model calls a "tour" (the two terms are synonymous).

MethodPathScopeIdempotency key required
POST/listingslistings:writeYes
GET/listingslistings:readNo
GET/listings/{listing_number}listings:readNo
GET/listings/{listing_number}/orderslistings:readNo
PATCH/listings/{listing_number}/statuslistings:writeYes
POST/listings/{listing_number}/cancellistings:writeYes
PATCH/listings/{listing_number}/sections/{section}listings:writeYes

POST /listings - Create a listing

Creates a new listing and returns its listing_number (the short slug used everywhere else in the API).

Required fields: address, owner_user_id, agent_one_id

Optional fields: agent_two_id, package, notes

Response: 201 Created with the full listing object including listing_number, status: "Coming Soon", and the canonical property page URL.

GET /listings - List listings

Returns a cursor-paginated list of listings owned by your agency.

Query params: cursor (pagination cursor), limit (1-200, default 50), status filter, agent_id filter.

GET /listings/{listing_number} - Get one listing

Returns the full listing object including status, address, assigned users, media sections, and order references.

GET /listings/{listing_number}/orders - Get listing orders

Returns orders and Square invoice state for a listing.

PATCH /listings/{listing_number}/status - Update status

Valid status values: Coming Soon, Active, Sold, Off Market.

Transitions must follow the listing lifecycle. Invalid transitions return 422 Unprocessable Entity with a lifecycle_violation error code.

POST /listings/{listing_number}/cancel - Cancel a listing

Cancels a listing. A 409 Conflict is returned if a cancellation window guard is active (e.g. shoot is within 24 hours).

PATCH /listings/{listing_number}/sections/{section} - Patch a section

Updates a listing section. section must be one of: matterport, floorplan.

Media (1 endpoint)

MethodPathScopeAuth
POST/media/uploadmedia:writeX-API-Key or session cookie (dual-auth endpoint)

Accepts multipart form data. Uploads are associated with a specific listing via the listing_number field in the form data.

Scheduling (1 endpoint)

MethodPathScope
GET/scheduling/availabilityscheduling:read

Returns available shoot time slots for a given address and package.

Users (1 endpoint)

MethodPathScope
GET/usersusers:read

Returns users in your agency hierarchy (team members, agents, assistants, viewers).

Webhook events catalog (1 endpoint)

MethodPathScope
GET/webhooks/eventswebhooks:read

Returns the full list of subscribable event types with payload schemas. This is the machine-readable version of the in-app catalog at /manage/webhooks/catalog.

Request conventions

Idempotency keys

Every state-changing request (POST, PATCH) MUST include an X-Idempotency-Key header. Use any UUID v4. The server caches the response for 24 hours keyed on (agency_id, idempotency_key). Retries with the same key return the cached response with X-Idempotent-Replay: true. A conflicting body returns 409.

POST /api/v1/listings HTTP/1.1
X-API-Key: sk_live_your_key_here
X-Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json

Pagination

List endpoints return:

{
"items": [...],
"next_cursor": "eyJpZCI6Ik9...",
"total": 142
}

Pass next_cursor value as ?cursor= on the next request. Empty string means end of collection.

Error envelope

All errors use a consistent JSON envelope:

{
"error": {
"code": "listing_not_found",
"message": "No listing with number ABC123 exists in your agency.",
"request_id": "req_01HXREQUESTID"
}
}

Include request_id in any support request - it correlates to the exact log entry in our backend.