Data Model
Managed data that the agent creates automatically, plus the REST API for direct access.
How data works in Galadri
The agent automatically creates and maintains structured records as users interact. When someone says "I have a 2022 Honda Civic," the agent creates a vehicle record. When they describe service history or upcoming maintenance, milestone and schedule records appear. You can also read and write the same records directly through the REST API.
Each end user gets their own scoped data: vehicles, documents (insurance, registration, receipts), milestones (service events, maintenance), and schedules (upcoming appointments and automations). All of this is queryable through the REST API and can be maintained by agents during a chat session when data access is enabled.
Managed data covers six public table families: end_users, vehicles, vehicle_groups, documents, milestones, and schedules. The field lists below match Galadri's current write contract, with REST-only exceptions called out separately.
Every conversation automatically loads the user's current vehicles, upcoming schedules, recent milestones, and documents into the agent's context. This is not a retrieval step you configure. It happens automatically.
Reference arrays such as vehicle_ids accept up to 100 UUIDs per field. Referenced records must belong to the same organization and, when the endpoint is scoped to a user, the same end user.
Real-time data events
When the agent creates or updates managed data, your client receives a data_saved event via the SSE stream. This lets your UI update in real time without polling.
The event contains a mutations array. Each mutation includes the action that was performed, the table that was affected, and the full record after the change.
{
"type": "data_saved",
"mutations": [
{
"action": "create",
"table": "vehicles",
"record": {
"id": "a1b2c3d4-...",
"year": 2022,
"make": "Honda",
"model": "Civic",
"nickname": "Daily commuter",
"trim": "EX",
"odometer_km": 34500,
"created_at": "2026-03-31T14:22:00Z"
}
}
]
}Handle this event on the client to keep your UI in sync as the agent works:
for (const line of lines) {
if (!line.startsWith("data: ")) continue;
const payload = line.slice(6);
if (payload === "[DONE]") break;
const event = JSON.parse(payload);
if (event.type === "data_saved") {
for (const mutation of event.mutations) {
switch (mutation.table) {
case "vehicles":
refreshVehicleList(mutation.record);
break;
case "schedules":
addToCalendar(mutation.record);
break;
case "milestones":
updateServiceHistory(mutation.record);
break;
}
}
}
}REST API and managed data are the same records
All data is also accessible via the REST API. The managed data layer and the REST API operate on the same records. Use the REST API for bulk operations, dashboards, and integrations outside of chat.
REST API Reference
Galadri stores structured data on behalf of your application's users. All data is scoped to your organization and a specific end user. Data can be created and managed in two ways:
- Via the Chat API - agents can create, read, update, list, and delete managed records through natural conversation, subject to the selected agent's data access settings.
- Via REST endpoints - use the Users, Vehicles, Vehicle Groups, Documents, Milestones, Schedules, Sessions, and Session Messages endpoints for direct programmatic access.
REST endpoint matrix
| Field | Type | Description |
|---|---|---|
/v1/users | GET, POST | List end users or upsert an end-user profile by external_id. |
/v1/users/:id | GET, PATCH, DELETE | Read, update, or soft-delete one end user by Galadri UUID. |
/v1/vehicles | GET, POST | List or create vehicles for an end user. |
/v1/vehicles/:id | GET, PATCH, DELETE | Read, update, or soft-delete one vehicle by UUID. |
/v1/vehicles/:id/refresh | POST | Refresh explicitly requested vendor-backed telemetry, DTC, and valuation fields without invoking chat. |
/v1/vehicle-groups | GET, POST | List or create named vehicle collections for an end user. |
/v1/vehicle-groups/:id | GET, PATCH, DELETE | Read, update, or soft-delete one vehicle group by UUID. |
/v1/documents | GET, POST | List or create document metadata records for an end user. |
/v1/documents/:id | GET, PATCH, DELETE | Read, update, or soft-delete one document by UUID. |
/v1/milestones | GET, POST | List or create service history and due-item records for an end user. |
/v1/milestones/:id | GET, PATCH, DELETE | Read, update, or soft-delete one milestone by UUID. |
/v1/schedules | GET, POST | List or create calendar entries, reminders, and automation schedules for an end user. |
/v1/schedules/:id | GET, PATCH, DELETE | Read, update, or soft-delete one schedule by UUID. |
/v1/sessions | GET | List chat sessions for one end user. |
/v1/sessions/:id | GET, PATCH, DELETE | Read a session, update unread or developer visibility metadata, or soft-delete it. |
/v1/sessions/:id/messages | GET | List messages for one chat session. |
REST scoping rules
/v1/users uses your external_id as the upsert key. Child collection endpoints such as /v1/vehicles require user_id, which is that same external ID. Single-record endpoints use the Galadri UUID returned in the record's id field.
Metric units
All measurements are stored in metric units (kilometers, liters, Celsius). The AI agent converts to the user's preferred units in conversation based on their profile settings.
Managed Tables
| Field | Type | Description |
|---|---|---|
end_users | profile | The end user's profile, preferences, contact info, and communication opt-ins. This is the root record for everything else. |
vehicles | asset | Per-vehicle facts such as make/model/year, odometer, registration details, and lightweight estimate fields used for UI shorthand. |
vehicle_groups | organization | Named collections of vehicles like fleets, family cars, or work trucks. Use these when schedules or reminders should target multiple vehicles together. |
documents | file metadata | Metadata and extracted analysis for uploaded or linked files such as receipts, inspections, insurance cards, registrations, titles, and condition photos. |
milestones | history / due item | Service history and ownership lifecycle events. Use milestones for completed work and upcoming due items, not for generic reminders. |
schedules | calendar / automation | Appointments, reminders, recurring events, and AI-triggered outbound communications. Use schedules for things that happen at a date/time or should fire automatically. |
Communication continuity records
Galadri also maintains communication-specific records outside the managed tables above. These are runtime continuity tables for email, SMS, and phone workflows, not user-authored business objects.
| Field | Type | Description |
|---|---|---|
chat_sessions / messages | conversation memory | End-user chat history. Messages store organization_id, chat_session_id, and denormalized end_user_id so conversation-history retrieval, retention, and user-scoped governance can filter directly before returning bounded snippets. |
email_threads / email_messages | communication | Outbound and inbound email history, reply tracking, and the sender identity used for each thread. |
sms_threads / sms_messages | communication | Outbound and inbound SMS or MMS history for a specific user and phone-number pair. |
call_sessions / voice_threads | communication | Inbound and outbound voice-call history plus durable voice continuity threads. Callback voice threads can link to either phone-call callback objectives or SMS callback objectives when an outside business switches channels. |
voice_callback_objectives | callback continuity | Destination-scoped callback objectives for outbound phone calls placed to external contacts on behalf of a user. They track the owning Twilio credential, active-query state, status, and follow-up channel. |
comm_callback_objectives | callback continuity | Destination-scoped email and SMS callback cases for external contacts. These stay durable and auditable, track whether Galadri is actively waiting on a response, store the user follow-up channel to use when the callback resolves, and remain available in a short recent-resolved window for continuity. |
external_contact_conversations | callback continuity | External email or phone/text conversations keyed by the destination credential plus the outside sender identity. They are created only when a scoped callback candidate exists or is bound, then track the active case, recent candidates, rolling summary, and continuity state while the initiating agent clarifies, continues outreach, or follows up on behalf of a user. |
external_contact_conversation_events | callback audit | Append-only audit events for external-contact callback state transitions, including clarification requests and when a conversation binds to, switches between, reopens, or resolves an email, SMS, or voice callback case. |
communication_contact_preferences | communication preference | Per-organization channel preferences keyed by sender and recipient address. SMS, email, and phone delivery use these records to add required disclosures where applicable and honor opt-out state for end users and external contacts. |
End Users
End users are your application's users. Each end user gets their own scoped data. Users are identified by the end_user_id you provide in chat requests. If the user does not exist, one is created automatically.
/v1/usersCreate or update an end user. If a user with the same external_id already exists in your organization, it is updated (upsert).
| Field | Type | Description |
|---|---|---|
id | UUID | Auto-generated record ID. |
first_name | string | User's first name |
last_name | string | User's last name |
email | string | Email address |
phone | string | Phone number (E.164 format) |
user_type | "individual" | "business" | User type: individual or business |
external_id | string | Developer's own user ID for cross-referencing |
street_address | string | Street address |
city | string | City |
state | string | State/province |
zip | string | ZIP/postal code |
country | string | Country (ISO 3166-1 alpha-2) |
timezone | string | IANA timezone (e.g. America/New_York) |
distance_unit | "km" | "mi" | Preferred distance unit: km or mi |
volume_unit | "liters" | "gallons" | Preferred volume unit: liters or gallons |
temperature_unit | "celsius" | "fahrenheit" | Preferred temperature unit: celsius or fahrenheit |
fuel_economy_unit | "l_per_100km" | "mpg" | "km_per_l" | Preferred fuel economy unit: l_per_100km, mpg, or km_per_l |
speed_unit | "kph" | "mph" | Preferred speed unit: kph or mph |
pressure_unit | "kpa" | "psi" | "bar" | Preferred pressure unit: kpa, psi, or bar |
currency | string | Preferred currency (ISO 4217, e.g. USD, EUR) |
marketing_opt_in | boolean | Opted in to marketing communications |
sms_opt_in | boolean | Opted in to SMS messages |
call_opt_in | boolean | Opted in to phone calls |
email_opt_in | boolean | Opted in to email communications |
other_archival_memory | string | Long-term user-level automotive context, preferences, constraints, and ownership or logistics notes that do not fit structured fields. Send a complete merged value on update because the field replaces prior text. |
/v1/usersList end users with filtering, sorting, and pagination.
Query parameters
| Parameter | Type | Description |
|---|---|---|
limit | integer | Results per page (1-100, default 20). |
offset | integer | Number of results to skip (0-based). |
sort | string | Sort field: created_at, updated_at, first_name, last_name, email, external_id. |
order | string | "asc" or "desc". |
filter.* | string | Filter by column. E.g., filter.city=Phoenix&filter.user_type=individual. Filterable: external_id, email, phone, first_name, last_name, city, state, country, user_type. |
{
"data": [
{
"id": "a1b2c3d4-...",
"external_id": "user-123",
"first_name": "Jane",
"last_name": "Smith",
"email": "jane@example.com",
"city": "Phoenix",
"state": "AZ",
"timezone": "America/Phoenix",
"distance_unit": "mi",
"created_at": "2026-03-20T10:30:00Z",
"updated_at": "2026-03-20T10:30:00Z"
}
],
"pagination": {
"total": 1,
"limit": 20,
"offset": 0,
"has_more": false
}
}Vehicles
/v1/vehiclesCreate a vehicle for an end user. The user_id field is your application's external ID for the end user (the same value you pass as end_user_id in chat requests).
| Field | Type | Description |
|---|---|---|
user_id | string (required) | Your application's external ID for the end user. |
id | UUID | Auto-generated record ID. |
vin | string | 17-character vehicle identification number. |
year | integer | Model year |
make | string | Manufacturer (e.g. Toyota) |
model | string | Model name (e.g. Camry) |
trim | string | Trim level (e.g. SE, XLE) |
color | string | Exterior color |
nickname | string | User's nickname for the vehicle |
license_plate | string | License plate number |
license_plate_state | string | License plate state or province |
powertrain | "bev" | "hybrid" | "ice" | Powertrain type: bev, hybrid, or ice |
image_urls | string[] | Array of image URLs (front, back, interior, damage photos) |
odometer_km | integer | Current odometer reading in kilometers. Automatically refreshed from telemetry snapshots when vehicle write access is enabled, VINs do not conflict, and a timestamped odometer value is available. |
last_odometer_update_utc | ISO 8601 with timezone offset | When the odometer was last updated. Automatically refreshed from telemetry snapshots when vehicle write access is enabled and VINs do not conflict. |
last_latitude | number | Last known vehicle latitude. Automatically refreshed from telemetry snapshots when vehicle write access is enabled, VINs do not conflict, and timestamped location is available. |
last_longitude | number | Last known vehicle longitude. Automatically refreshed from telemetry snapshots when vehicle write access is enabled, VINs do not conflict, and timestamped location is available. |
last_geo_update_utc | ISO 8601 with timezone offset | When the vehicle location was last updated. Automatically refreshed from telemetry snapshots when vehicle write access is enabled and VINs do not conflict. |
dtc_codes | string[] | Active diagnostic trouble codes. Automatically refreshed from telemetry snapshots when vehicle write access is enabled, VINs do not conflict, and a timestamped DTC list is available. |
last_dtc_update_utc | ISO 8601 with timezone offset | When the active diagnostic trouble code list was last refreshed from a vendor-backed telemetry snapshot. |
ownership_status | "owned" | "leased" | "financed" | "other" | Ownership status: owned, leased, financed, or other |
service_bias | "cheap" | "moderate" | "premium" | Service preference: cheap, moderate, or premium |
registered_country | string | Country of registration (ISO 3166-1 alpha-2) |
registered_sub_region | string | State/province of registration |
est_tank_capacity_liters | number | Estimated fuel tank capacity in liters. For a new ICE or non-plug-in hybrid vehicle, prefer a reasonable make/model/year ballpark value over leaving this blank. |
octane_rating | integer | Typical gasoline octane rating for this vehicle, as an integer from 87 through 94. |
recommended_front_tire_pressure_min_psi | integer | Recommended cold front tire pressure lower bound in PSI. |
recommended_front_tire_pressure_max_psi | integer | Recommended cold front tire pressure upper bound in PSI. |
recommended_rear_tire_pressure_min_psi | integer | Recommended cold rear tire pressure lower bound in PSI. |
recommended_rear_tire_pressure_max_psi | integer | Recommended cold rear tire pressure upper bound in PSI. |
est_ev_battery_capacity_kwh | number | Estimated EV battery capacity in kWh. For a new BEV or plug-in hybrid vehicle, prefer a reasonable make/model/year ballpark value over leaving this blank. |
est_kwh_per_100km | number | Estimated energy consumption in kWh per 100km (EVs). For a new BEV or plug-in hybrid vehicle, prefer a reasonable ballpark value over leaving this blank. |
est_liters_per_100km | number | Estimated fuel consumption in liters per 100km (ICE/hybrid). For a new ICE or hybrid vehicle, prefer a reasonable ballpark value over leaving this blank. |
est_maintenance_per_100km_cents | integer | Variable maintenance cost per 100km in cents (USD) — the mileage-driven half of total maintenance. Covers items that wear with use: tires, brake pads, oil consumed between intervals, wiper blades. The fixed half (calendar items that happen regardless of miles) lives in est_annual_maintenance_cents. For a new vehicle, prefer a reasonable ballpark value over leaving this blank. |
est_annual_maintenance_cents | integer | Fixed annual maintenance cost in cents (USD) — the time-based half of total maintenance, independent of miles driven. Covers calendar items: annual inspection, registration-adjacent services, brake fluid and coolant flushes amortized, age-based 12V battery and tire replacement amortized, A/C service. Pairs with est_maintenance_per_100km_cents (the mileage-driven half) to give a total. Typical fixed-only ranges: economy ~$300, midsize ~$500, luxury/performance ~$700-1100, BEV ~$200. |
monthly_insurance_payment_cents | integer | Monthly insurance payment in cents (USD). |
monthly_lease_payment_cents | integer | Monthly lease payment in cents (USD). |
lease_start_date | ISO 8601 with timezone offset | Lease start timestamp (ISO 8601 with timezone offset). |
lease_end_date | ISO 8601 with timezone offset | Lease end timestamp (ISO 8601 with timezone offset). |
lease_buyout_price_cents | integer | Lease buyout price in cents (USD). |
lease_other_terms | string | Other lease terms (free-text notes) |
monthly_loan_payment_cents | integer | Monthly loan payment in cents (USD). |
loan_start_date | ISO 8601 with timezone offset | Loan start timestamp (ISO 8601 with timezone offset). |
loan_final_payment_date | ISO 8601 with timezone offset | Loan final payment timestamp (ISO 8601 with timezone offset). |
finance_down_payment_cents | integer | Lease or loan down payment in cents (USD). |
finance_interest_rate_percent | number | Lease or loan annual percentage rate stored as a percentage value. |
retail_valuation_cents | integer | Best available dealer retail value estimate in cents. Automatically refreshed from valuation lookups when vehicle write access is enabled and VINs do not conflict. |
last_valuation_update_utc | ISO 8601 with timezone offset | When the dealer retail valuation fields were last refreshed. |
valuation_insight | string | Customer-facing prose (1-2 sentences), AI judgment only — never capability-generated. For owned/financed vehicles speaks to sell-vs-hold; for leased vehicles speaks to buyout-vs-return. |
time_to_sell_score | number | AI judgment from 0.0 to 1.0. Owned/financed: 0 = hold, 1 = sell now. Leased: 0 = return at term end, 1 = definitely buy out. |
other_archival_memory | string | Long-term vehicle-specific facts such as condition, modifications, accessories, recurring quirks, and context that do not fit structured fields. Send a complete merged value on update because the field replaces prior text. |
telemetry_system_id | string | null | Developer-managed external vehicle ID for a telematics provider such as DIMO, Geotab, or Samsara. For DIMO, store the DIMO token ID as a string. Returned by the vehicle REST API, but intentionally not exposed to the AI agent. |
Estimated vehicle fields
Fields prefixed with est_ are intentionally approximate. They are usually written by the agent or filled from conservative make and model defaults during vehicle creation when omitted. They are meant for quick UI reference, not as authoritative vendor lookups, telemetry, or personalized total cost accounting.
Vendor-refreshable vehicle fields
Vehicle nickname is a normal writable string field. Odometer and last-location fields are also writable through the REST API, but DIMO snapshot reads automatically refresh odometer_km, last_odometer_update_utc, last_latitude, last_longitude, last_geo_update_utc, dtc_codes, and last_dtc_update_utc when vehicle write access is enabled, the provider returns timestamped values, and the VINs do not conflict.
Valuation lookups refresh retail_valuation_cents, last_valuation_update_utc, valuation_source and valuation_method with the best available dealer-retail estimate and provenance. valuation_insight and time_to_sell_score stay judgment fields for the agent or your application to write.
If the application updates retail_valuation_cents or valuation_insight without an explicit valuation timestamp, the database automatically refreshes last_valuation_update_utc.
Use POST /v1/vehicles/:id/refresh with explicit targets to refresh only the telemetry, DTC, or valuation fields your backend needs without starting a chat turn.
Developer-only telemetry mapping
telemetry_system_id is writable through POST /v1/vehicles and PATCH /v1/vehicles/:id, and it is returned by the REST API. Galadri intentionally excludes this field from agent-managed writes and model context, so agents cannot read or edit provider-specific IDs.
/v1/vehiclesList vehicles for an end user. The user_id query parameter is required.
Query parameters
| Parameter | Type | Description |
|---|---|---|
user_idrequired | string | External ID of the end user. |
limit | integer | Results per page (1-100, default 20). |
offset | integer | Number of results to skip. |
sort | string | Sort field: created_at, updated_at, year, make, model, nickname. |
order | string | "asc" or "desc". |
filter.* | string | Filter by column: vin, year, make, model, trim, color, license_plate, license_plate_state, powertrain, octane_rating, recommended_front_tire_pressure_min_psi, recommended_front_tire_pressure_max_psi, recommended_rear_tire_pressure_min_psi, recommended_rear_tire_pressure_max_psi, ownership_status, lease_start_date, lease_end_date, loan_start_date, loan_final_payment_date, finance_down_payment_cents, finance_interest_rate_percent, nickname. |
/v1/vehicles/:id/refreshRefresh explicitly requested vendor-backed vehicle fields directly. targets is required so organizations without telematics credentials can request valuation without triggering a telemetry lookup.
{
"targets": ["dtc_codes", "valuation"],
"valuation": {
"dealer_type": "independent",
"zip": "02139"
}
}Request body
| Parameter | Type | Description |
|---|---|---|
targetsrequired | array | Refresh targets to run: telemetry, dtc_codes, valuation, or a combination. Galadri never defaults this value. |
telemetry.unit_system | string | Optional output unit system for the telemetry result: user_preference, metric, imperial, us, or uk. |
telemetry.timezone | string | Optional IANA timezone for user-facing telemetry local time fields. |
dtc_codes | target | Runs a telemetry snapshot and refreshes dtc_codes plus last_dtc_update_utc when the provider returns a timestamped DTC list. |
valuation.dealer_typerequired | string | Required for valuation refresh. Must be franchise or independent. |
valuation.miles | number | Optional odometer in miles. If omitted, Galadri converts the saved odometer_km. |
valuation.zip | string | ZIP code for valuation. If omitted, Galadri uses the end-user profile ZIP when available. |
valuation.city | string | City for valuation. Pair with valuation.state when ZIP is omitted. |
valuation.state | string | State for valuation. Pair with valuation.city when ZIP is omitted. |
valuation.is_certified | boolean | Optional certified-preowned valuation hint. |
The response includes a refresh object keyed by requested target and the latest vehicle row after refresh attempts. The top-level status is success, partial_success, or error. Target execution failures are also returned inside the target result with status: "error". Mixed target outcomes return HTTP 200 with partial_success. If every requested target fails, Galadri returns HTTP 502 with status: "error". Authentication, validation, vehicle lookup, and credit failures use their normal non-200 status codes.
{
"status": "success",
"data": {
"vehicle_id": "550e8400-e29b-41d4-a716-446655440000",
"refreshed_at_utc": "2026-04-28T21:35:00.000Z",
"refresh": {
"dtc_codes": {
"status": "success",
"data": {
"source": "telemetry_snapshot",
"dtc_codes": ["P0301", "P0420"],
"last_dtc_update_utc": "2026-04-28T21:34:58.000Z"
}
},
"valuation": {
"status": "success",
"data": {
"estimated_dealer_retail_price_cents": 1875000,
"vehicle_sync": {
"status": "updated",
"fields_synced": [
"retail_valuation_cents",
"last_valuation_update_utc",
"valuation_source",
"valuation_method"
]
},
"persistence": {
"saved_to_vehicle_row": [
"retail_valuation_cents",
"last_valuation_update_utc",
"valuation_source",
"valuation_method"
],
"not_saved_requires_your_judgment": [
"valuation_insight",
"time_to_sell_score"
]
}
}
}
},
"vehicle": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"dtc_codes": ["P0301", "P0420"],
"last_dtc_update_utc": "2026-04-28T21:34:58.000Z",
"retail_valuation_cents": 1875000,
"valuation_source": "marketcheck_price",
"valuation_method": "marketcheck_price"
}
}
}Sessions
/v1/sessionsList chat sessions. Sessions are created automatically by the chat endpoint. Use PATCH /v1/sessions/:id to update hidden or unread, DELETE /v1/sessions/:id to soft-delete, and GET /v1/sessions/:id/messages to read messages.
The hidden flag is a developer convenience for your own chat-history UI. It does not delete the session, remove it from the Sessions API, or hide it from the Galadri Console data browser.
Query parameters
| Parameter | Type | Description |
|---|---|---|
user_idrequired | string | External ID of the end user. |
limit | integer | Results per page (1-100, default 20). |
offset | integer | Number of results to skip. |
sort | string | Sort field: created_at, updated_at, title, venue. |
filter.venue | string | Filter by session venue. |
filter.agent_id | string | Filter by agent UUID. |
filter.unread | boolean | Filter by unread status. |
filter.hidden | boolean | Filter by hidden status. |
Vehicle Groups
Vehicle groups let users organize vehicles into named collections (e.g., "Fleet A", "Family cars"). Groups are managed by agents in chat or through the Vehicle Groups REST endpoints.
Group membership is canonical on the vehicle group record itself via vehicle_ids. Vehicles do not carry a mirrored inverse array of group IDs.
| Field | Type | Description |
|---|---|---|
user_id | string (required) | Your application's external ID for the end user on create and list requests. |
id | UUID | Auto-generated record ID. |
name | string | Group name |
description | string | Group description |
vehicle_ids | UUID[] | UUID array of vehicles in this group |
Documents
Documents store metadata about files associated with vehicles or end users (receipts, insurance cards, registration papers, etc.).
| Field | Type | Description |
|---|---|---|
user_id | string (required) | Your application's external ID for the end user on create and list requests. |
id | UUID | Auto-generated record ID. |
title | string | Document title |
type | "receipt" | "insurance" | "registration" | "title" | "inspection" | "warranty" | "loan" | "lease" | "other" | Document type: receipt, insurance, registration, title, inspection, warranty, loan, lease, or other |
file_url | string | URL of the uploaded file |
key_info | string | Brief extracted summary of the document. |
full_analysis | string | Comprehensive extracted analysis and details from the document. |
notes | string | Notes about this document. |
vehicle_ids | UUID[] | UUID array of vehicles this document relates to |
Milestones
Milestones track service events, maintenance, and other vehicle lifecycle events.
A milestone can begin as an upcoming due item and later be updated with completion details when the work actually happens. Agents should prefer updating a matching open milestone before creating a duplicate completion record.
| Field | Type | Description |
|---|---|---|
user_id | string (required) | Your application's external ID for the end user on create and list requests. |
id | UUID | Auto-generated record ID. |
type | "oil" | "12v_battery" | "tire_rotation" | "tire_replacement" | "registration" | "inspection" | "sale" | "insurance_renewal" | "drivers_license_renewal" | "other" | Milestone type: oil, 12v_battery, tire_rotation, tire_replacement, registration, inspection, sale, insurance_renewal, drivers_license_renewal, or other |
title | string | Short title (e.g. 'Oil Change at Jiffy Lube') |
completion_utc | ISO 8601 with timezone offset | When this was completed (ISO 8601 with timezone offset) |
completion_km | integer | Odometer at completion (km) |
completion_price_cents | integer | Cost in cents (USD) |
next_due_utc | ISO 8601 with timezone offset | When this is next due (ISO 8601 with timezone offset) |
next_due_km | integer | Odometer when next due (km) |
next_due_estimated_price_cents | integer | Estimated cost for the next service in cents (USD) |
performed_by_name | string | Who performed the service (shop name, dealer, DIY) |
performed_by_address | string | Address of the service provider |
performed_by_phone | string | Phone number of the service provider |
performed_by_email | string | Email address of the service provider |
other_archival_memory | string | Additional notes or context about this milestone |
vehicle_ids | UUID[] | UUID array of vehicles this milestone relates to |
document_ids | UUID[] | UUID array of related documents (receipts, reports) |
Schedules
Schedules represent upcoming appointments, events, and automated communications. A schedule can be a simple calendar entry or an AI-triggered action that sends reminders via email, SMS, voice call, or webhook.
| Field | Type | Description |
|---|---|---|
user_id | string (required) | Your application's external ID for the end user on create and list requests. |
id | UUID | Auto-generated record ID. |
title | string | What the appointment is for, subject only (e.g. 'Oil change', 'Battery replacement'). Aim for 2-6 words. Excludes the business name, address, phone, date, time, or vehicle because each has its own column. |
description | string | Event description |
attendees | string[] | Array of attendee email addresses |
special_instructions | string | Special instructions for the appointment |
start_time_utc | ISO 8601 with timezone offset | When the event occurs (ISO 8601 with timezone offset). Required for calendar events, optional for pure automations. |
end_time_utc | ISO 8601 with timezone offset | End time (ISO 8601 with timezone offset) |
agent_runtime_utc | ISO 8601 with timezone offset | When Galadri should run the scheduled automation (ISO 8601 with timezone offset). Separate from start_time_utc, which is the actual event time. |
recurring | boolean | Whether the schedule repeats. Recurring automated reports pair this with frequency fields, agent_runtime_utc, agent_runtime_prompt, and agent_comm_channel. |
frequency_type | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | Recurrence frequency: hourly, daily, weekly, monthly, or yearly |
frequency_interval | integer | Recurrence interval (e.g. 2 for 'every 2 weeks') |
location_name | string | Just the business or place name (e.g. 'Pep Boys', 'Home', 'Office'). Excludes the street address, city, state, ZIP, and phone because those have their own columns. |
location_address | string | Just the street address a customer would type into Google Maps to navigate. Excludes the business name, phone, hours, or any commentary. |
location_phone | string | Location phone number, digits only or formatted, no extension labels. One number, not a list. |
location_email | string | Location email address |
odometer_km | integer | Odometer reading that triggers this schedule (km) |
odometer_trigger | boolean | Whether this schedule is triggered by odometer instead of time. Mutually exclusive with recurring. Fires once when vehicle odo exceeds odometer_km, then auto-completes. |
agent_runtime_prompt | string | Instruction for the scheduled automation at agent_runtime_utc, including monitoring or reporting tasks. |
agent_comm_channel | "email" | "sms" | "call" | "webhook" | Delivery channel for the scheduled automation: email, sms, call, or webhook. |
agent_id | UUID | UUID of the Galadri agent assigned to this schedule. Falls back to the organization's first active agent if null. |
is_completed | boolean | Whether this event/task is completed |
vehicle_ids | UUID[] | UUID array of vehicles related to this event |
vehicle_group_ids | UUID[] | UUID array of vehicle groups |
agent_runtime_utc vs start_time_utc
These are intentionally separate. An oil change scheduled for September 8 at 8am (start_time_utc) might trigger the AI three days earlier (agent_runtime_utc = September 5) to send a reminder. See the Scheduled Communications section for the full execution flow.
Automation-only schedules
Creating a schedule without start_time_utc is valid for pure automations. Provide agent_runtime_prompt, agent_comm_channel, and either agent_runtime_utc or an odometer trigger with odometer_km.
Agent-managed Updates
Agents can maintain managed records during Chat API requests when data access is enabled.end_users is profile-scoped to the current user. The other managed tables create separate records scoped to the same user. Your application should not construct internal agent operations directly. Use the Chat API for conversational updates and the REST endpoints for direct writes.
| Field | Type | Description |
|---|---|---|
read_write_delete | agent data access | The agent can create, read, update, list, and delete managed records during chat, except end_users which can never be deleted through manage-data. |
read_write | agent data access | The agent can create, read, update, and list managed records during chat. Delete attempts are blocked. |
read | agent data access | The agent can read and list managed records but cannot write changes. |
none | agent data access | The agent cannot access managed records. |
Estimate fields are the exception
Most fields in these tables should come from the user, uploaded files, API lookups, or concrete workflow results. The main exception is the small set of vehicle fields prefixed with est_, which are intentionally allowed to be agent-authored ballpark values for UI shorthand.
Building a data-driven UI
Combine the REST endpoints (for initial data loading and direct CRUD) with data_saved events (for real-time updates during AI conversations) to build a responsive data layer in your application.
Data Access Permissions
Each agent can be configured with a data access level that controls what it can read or change in managed data. See Data Access for details.
| Field | Type | Description |
|---|---|---|
read_write_delete | elevated | Full CRUD access for supported tables. The agent can create, read, update, and delete records. |
read_write | default | Create, read, update, and list access. Delete attempts are blocked. |
read | restricted | Read and list only. Writes are blocked. |
none | restricted | No managed data access. |
System Fields
Every record includes these auto-managed fields. You do not need to set them when creating records.
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier. Auto-generated on create. |
organization_id | UUID | Your organization ID. Set automatically from the API key. |
end_user_id | UUID | Internal ID of the end user. Set automatically from user_id, session context, or the current chat user depending on path. |
created_at | ISO 8601 | Timestamp when the record was created. |
updated_at | ISO 8601 | Timestamp when the record was last updated. |
deleted_at | ISO 8601 | null | Soft delete timestamp. Null if the record is active. |