Scribe API Reference
This document provides complete API reference for integrating with Scribe’s session management and preference detection system.
Session Management
Section titled “Session Management”Get Scribe Status
Section titled “Get Scribe Status”Retrieve current session preferences and readiness state.
GET /sessions/scribe-statusResponse
Section titled “Response”{ "ready": true, "session_age_minutes": 15, "properties_viewed": 8, "average_confidence": 72, "preferences": { "price": { "min": 400000, "max": 600000, "confidence": 85, "source": "inferred" }, "bedrooms": { "min": 3, "confidence": 75, "source": "inferred" }, "locations": [ { "value": "Twin Falls", "confidence": 90, "source": "inferred" } ], "features": [ { "key": "pool", "value": "Pool", "confidence": 65, "source": "inferred" } ] }, "freeform_notes": "Need to be near Lincoln Elementary", "assigned_agent_id": null}Status Codes
Section titled “Status Codes”| Code | Meaning |
|---|---|
| 200 | Success, status returned |
| 404 | No session found |
Get Suggested Agents
Section titled “Get Suggested Agents”Retrieve matched agents for current session preferences.
GET /sessions/suggested-agentsResponse
Section titled “Response”{ "agents": [ { "id": "agent_123", "name": "Jane Smith", "email": "jane@example.com", "photo_url": "https://...", "match_score": 87, "match_label": "Excellent Match", "best_match": true, "reasons": [ "Specializes in Twin Falls family homes", "Expert in $400k-$600k price range" ] }, { "id": "agent_456", "name": "John Doe", "email": "john@example.com", "photo_url": "https://...", "match_score": 68, "match_label": "Great Match", "best_match": false, "reasons": [ "Knows the best neighborhoods with pools" ] } ]}Query Parameters
Section titled “Query Parameters”| Parameter | Type | Description |
|---|---|---|
limit | integer | Maximum agents to return (default: 3, max: 10) |
Status Codes
Section titled “Status Codes”| Code | Meaning |
|---|---|
| 200 | Success, agents returned |
| 400 | Preferences not ready (insufficient confidence) |
| 404 | No session found |
Assign Agent to Session
Section titled “Assign Agent to Session”Assign a selected agent to the visitor’s session.
POST /sessions/assign-agentContent-Type: application/json
{ "agent_id": "agent_123"}Response
Section titled “Response”{ "success": true, "agent": { "id": "agent_123", "name": "Jane Smith", "email": "jane@example.com" }}Status Codes
Section titled “Status Codes”| Code | Meaning |
|---|---|
| 200 | Agent assigned successfully |
| 400 | Invalid agent_id |
| 404 | No session or agent not found |
Clear Session Data
Section titled “Clear Session Data”Delete all session data for the current visitor.
POST /sessions/clearResponse
Section titled “Response”{ "success": true, "message": "All session data cleared"}Status Codes
Section titled “Status Codes”| Code | Meaning |
|---|---|
| 200 | Data cleared successfully |
| 404 | No session found |
Preference Management
Section titled “Preference Management”Get All Preferences
Section titled “Get All Preferences”Retrieve all session preferences with confidence scores.
GET /sessions/preferencesResponse
Section titled “Response”{ "price": { "min": 400000, "max": 600000, "confidence": 85, "source": "inferred", "confirmed": false }, "bedrooms": { "min": 3, "confidence": 100, "source": "user_added", "confirmed": true }, "locations": [ { "value": "Twin Falls", "confidence": 90, "source": "inferred", "confirmed": false } ], "features": [ { "key": "pool", "value": "Pool", "confidence": 65, "source": "inferred", "confirmed": false } ], "negative": [ { "type": "property_type", "value": "condo", "confidence": 75, "source": "inferred" } ]}Create User-Added Preference
Section titled “Create User-Added Preference”Manually add a preference with 100% confidence.
POST /sessions/preferencesContent-Type: application/json
{ "type": "features", "key": "home_office", "value": "Home office space"}Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | price, bedrooms, bathrooms, locations, features, property_types |
key | string | Sometimes | Required for features and property_types |
value | string/number | Yes | Preference value |
Response
Section titled “Response”{ "success": true, "preference": { "type": "features", "key": "home_office", "value": "Home office space", "confidence": 100, "source": "user_added" }}Status Codes
Section titled “Status Codes”| Code | Meaning |
|---|---|
| 201 | Preference created |
| 400 | Invalid request body |
| 404 | No session found |
Confirm or Reject Preference
Section titled “Confirm or Reject Preference”Update confidence on an inferred preference.
POST /sessions/preferences/{type}/{key}/confirmContent-Type: application/json
{ "action": "confirm"}Path Parameters
Section titled “Path Parameters”| Parameter | Description | Example |
|---|---|---|
type | Preference type | features, locations, price |
key | Preference key | pool, twin_falls, budget |
Request Body
Section titled “Request Body”| Field | Type | Values | Effect |
|---|---|---|---|
action | string | confirm | Sets confidence to 100% |
reject | Sets confidence to 0% (excluded from matching) |
Response
Section titled “Response”{ "success": true, "preference": { "type": "features", "key": "pool", "value": "Pool", "confidence": 100, "source": "inferred", "confirmed": true }}Status Codes
Section titled “Status Codes”| Code | Meaning |
|---|---|
| 200 | Preference updated |
| 400 | Invalid action |
| 404 | Preference not found |
Delete User-Added Preference
Section titled “Delete User-Added Preference”Remove a manually added preference.
DELETE /sessions/preferences/{type}/{key}Response
Section titled “Response”{ "success": true, "message": "Preference deleted"}Status Codes
Section titled “Status Codes”| Code | Meaning |
|---|---|
| 200 | Preference deleted |
| 403 | Cannot delete inferred preference |
| 404 | Preference not found |
Save Freeform Notes
Section titled “Save Freeform Notes”Store visitor’s freeform preference text.
POST /sessions/preferences/notesContent-Type: application/json
{ "notes": "Need to be near Lincoln Elementary, home office space required"}Response
Section titled “Response”{ "success": true, "notes": "Need to be near Lincoln Elementary, home office space required"}Status Codes
Section titled “Status Codes”| Code | Meaning |
|---|---|
| 200 | Notes saved |
| 400 | Invalid notes (too long) |
| 404 | No session found |
Event Tracking
Section titled “Event Tracking”Batch Submit Events
Section titled “Batch Submit Events”Submit behavioral events for preference inference.
POST /sessions/eventsContent-Type: application/json
{ "events": [ { "type": "property_view", "listing_id": "12345", "timestamp": "2024-01-15T10:30:00Z", "engagement": { "time_seconds": 180, "scroll_percent": 85, "photos_viewed": 8 } }, { "type": "photo_engagement", "listing_id": "12345", "photo_index": 3, "dwell_ms": 5200, "zoomed": true, "timestamp": "2024-01-15T10:32:00Z" }, { "type": "filter_change", "filter": "price_max", "value": 600000, "timestamp": "2024-01-15T10:35:00Z" } ]}Event Types
Section titled “Event Types”property_view
Section titled “property_view”Tracks property page visits.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | property_view |
listing_id | string | Yes | MLS listing ID |
timestamp | ISO-8601 | Yes | Event time |
engagement | object | No | Engagement metrics |
engagement.time_seconds | number | No | Time on page |
engagement.scroll_percent | number | No | Max scroll depth (0-100) |
engagement.photos_viewed | number | No | Photo carousel views |
engagement.used_calculator | boolean | No | Used mortgage calculator |
engagement.downloaded_pdf | boolean | No | Downloaded flysheet |
photo_engagement
Section titled “photo_engagement”Tracks individual photo interactions.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | photo_engagement |
listing_id | string | Yes | MLS listing ID |
photo_index | number | Yes | Photo position (0-based) |
dwell_ms | number | Yes | Milliseconds viewing photo |
zoomed | boolean | No | Whether photo was zoomed |
timestamp | ISO-8601 | Yes | Event time |
filter_change
Section titled “filter_change”Tracks explicit filter applications.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | filter_change |
filter | string | Yes | Filter name (price_min, price_max, beds, baths, etc.) |
value | any | Yes | Filter value |
timestamp | ISO-8601 | Yes | Event time |
search_query
Section titled “search_query”Tracks natural language searches.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | search_query |
query | string | Yes | Search text |
timestamp | ISO-8601 | Yes | Event time |
favorite_added / favorite_removed
Section titled “favorite_added / favorite_removed”Tracks favorite actions.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | favorite_added or favorite_removed |
listing_id | string | Yes | MLS listing ID |
timestamp | ISO-8601 | Yes | Event time |
Response
Section titled “Response”{ "success": true, "processed": 3, "updated_preferences": ["price", "features"]}Status Codes
Section titled “Status Codes”| Code | Meaning |
|---|---|
| 200 | Events processed |
| 400 | Invalid event format |
| 404 | No session found |
Event Batching
Section titled “Event Batching”Client-side events are batched for efficiency:
| Setting | Value | Purpose |
|---|---|---|
| Debounce interval | 5 seconds | Wait time before sending batch |
| Max queue size | 50 events | Forces immediate flush when exceeded |
| Delivery method | fetch() with keepalive: true | Ensures delivery even during navigation |
| Page unload | navigator.sendBeacon() | Reliable delivery when closing tab |
Example Client Code
Section titled “Example Client Code”class ScribeEventBatcher { constructor() { this.queue = []; this.timer = null; }
track(event) { this.queue.push({ ...event, timestamp: new Date().toISOString() });
// Flush immediately if queue is full if (this.queue.length >= 50) { this.flush(); return; }
// Otherwise debounce clearTimeout(this.timer); this.timer = setTimeout(() => this.flush(), 5000); }
async flush() { if (this.queue.length === 0) return;
const events = [...this.queue]; this.queue = [];
await fetch('/sessions/events', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ events }), keepalive: true }); }}
// Ensure events are sent on page unloadwindow.addEventListener('beforeunload', () => { if (batcher.queue.length > 0) { navigator.sendBeacon( '/sessions/events', JSON.stringify({ events: batcher.queue }) ); }});Rate Limits
Section titled “Rate Limits”| Endpoint | Limit | Window |
|---|---|---|
/sessions/events | 100 requests | 15 minutes |
/sessions/preferences | 50 requests | 15 minutes |
| All other endpoints | 30 requests | 15 minutes |
Rate limit headers:
X-RateLimit-Limit: 100X-RateLimit-Remaining: 87X-RateLimit-Reset: 1705329600Related Documentation
Section titled “Related Documentation”- Understanding Scribe — Conceptual overview
- Using Scribe — Practical usage guide
- Scribe Detection Reference — Algorithms and thresholds