AtlasCare supports automated trip-option checks (availability + estimated pricing together) and online trip-request submission through this API. It's documentation for AI agents, facility systems, and other integrations — human customers should use the homepage estimate or Request a Trip, which calls this same API.
/api/v1/openapi.json (mirrored at /.well-known/openapi.json for tooling that checks there first) — point an agent framework at either URL instead of having it parse this page.AtlasCare Transport provides private, non-emergency medical transportation for adults — wheelchair-accessible and ambulatory — including hospital discharges, medical appointments, dialysis and treatment transport, and facility transfers. Every trip includes a private vehicle and driver, assisted door-to-door service, and one family member or caregiver at no extra charge. Wait & Return service keeps the vehicle and driver dedicated to a passenger's appointment.
McMinnville, Oregon and Yamhill County, with regional trips to the greater Portland and Salem areas. Requests outside this area are still accepted — they're routed to manual review rather than rejected.
v1 — base path /api/v1/. Breaking changes will use a new version prefix; this document always describes the current v1 contract.
None required for public use. Checking availability and price, and submitting with source web_wizard or ai_agent, need no key — those actions are read-only or create a non-binding trip request (see Important: Request vs. Booking), protected by network-level bot-abuse protection and a per-IP rate limit (see Rate Limiting & Fair Use). Such requests are recorded as self-declared.
Trusted channels need an API key. Submissions with source api_partner, phone_agent, facility_portal or staff must carry a key issued by AtlasCare, sent as Authorization: Bearer <key>. Without it the request is refused with 401 UNAUTHENTICATED; a key for a client not allowed that channel gets 403 SOURCE_NOT_ALLOWED; an unrecognized key gets 401 INVALID_API_KEY. A keyed request is recorded as coming from that verified client, and gets that client's own rate limits instead of the per-IP ones. To request a key, email support@atlascaretransport.com. Never put a key in browser code.
REQUEST_TRIP) never creates a confirmed, paid reservation by itself. It enters AtlasCare's normal staff review workflow. There is no public, unauthenticated CONFIRM_BOOKING action.round_trip, AtlasCare checks the pickup and the return leg against its service hours and the staff-maintained availability calendar, and the more restrictive of the two decides the overall availability.status. The return verdict is reported separately as availability.return_leg — see Round Trips & the Return Leg below, and read its basis before repeating a return time to anyone.POST /api/v1/trip-options. It is the default quote path — the one AtlasCare's own website uses — and returns serviceability, availability for both legs, pricing, a signed quote token, and a prefilled request URL in one call. Then submit with POST /api/v1/trip-requests. The narrower availability-only and price-only lookups are listed afterwards for callers that need just one of those answers.POST /api/v1/trip-options · operationId checkAvailabilityAndPrice
One request answers everything needed before a trip is requested:
serviceable is false when the trip appears to be outside the service area, its distance could not be calculated automatically, or the requested time is unavailable. A request can still be submitted for staff review in each case.availability.return_leg for a round trip, judged against real routed drive time.schedule: the pickup time and whether it was given or suggested from an appointment time (see Appointment Times & Transfers).equipment: whether the BRODA Traversa and a transfer board are required.quote.id and quote.token; pass the token to REQUEST_TRIP.plan.plan_number, e.g. ATP-2026-104233), and request_trip_url (/request-trip?plan=<token>) opens AtlasCare's Request a Trip page with the trip and quote already filled in, for a person to review and submit. The link carries no trip details, so it is safe to text or email; the token in it is the only key to the plan, so share it only with the person the trip is for. Send plan.token back as plan_token when you re-quote a changed trip (it becomes the next version of the same plan) and when you submit it with POST /api/v1/trip-requests (the same version is never submitted twice). GET /api/v1/plans/{token} returns the plan as its link shows it.{
"pickup_address": { "formatted": "2700 NW Stewart Pkwy, McMinnville, OR" },
"destination_address": { "formatted": "3181 SW Sam Jackson Park Rd, Portland, OR" },
"pickup_datetime": "2026-09-22T08:00:00-07:00",
"mobility_type": "wheelchair",
"trip_type": "round_trip",
"return_type": "wait_and_return",
"requested_wait_minutes": 90,
"broda_required": false
}
{
"serviceable": true,
"availability": {
"status": "available",
"label": "Available",
"message": "AtlasCare currently has availability for this trip.",
"requested_datetime": "2026-09-22T15:00:00.000Z",
"return_leg": {
"status": "available",
"reason_code": null,
"message": "The return trip also falls within the hours AtlasCare operates.",
"estimated_return_datetime": "2026-09-22T18:49:00.000Z",
"basis": "computed"
}
},
"quote": {
"id": "ATQ-260922-0P2M",
"token": "<opaque signed token>",
"status": "estimated",
"currency": "USD",
"pricing_tier": { "id": "extended_regional", "label": "Extended Regional Medical Transportation", "minMiles": 31, "maxMiles": 45 },
"one_way_miles": 38.4,
"duration_minutes": 62,
"duration_without_traffic_minutes": 48,
"traffic_delay_minutes": 14,
"traffic_aware": true,
"total": 370,
"one_way_price": 165,
"round_trip_price": 330,
"included_wait_minutes": 60,
"additional_wait_rate": { "amount": 20, "minutes": 15 },
"equipment_charges": [],
"reasons": [],
"disclosures": ["Estimate includes 30 minutes of additional wait time beyond the 60-minute included window, at $20 per 15 minutes."],
"created_at": "2026-09-15T16:00:00.000Z",
"expires_at": "2026-09-18T16:00:00.000Z"
},
"plan": { "plan_number": "ATP-2026-104233", "version": 1, "status": "draft", "token": "v6Hq…43 characters…" },
"request_trip_url": "/request-trip?plan=v6Hq…"
}
Drive time allows for traffic; the price does not. duration_minutes is Google's prediction for this trip's own departure date and time, so an 8 AM trip and a 2 AM trip on the same route come back differently. duration_without_traffic_minutes is the same drive ignoring traffic and traffic_delay_minutes is the difference between them. Use duration_minutes for arrival planning and for schedule.suggested_pickup_datetime. Pricing is mileage-based, so none of these move total — the same trip costs the same at rush hour as it does at midnight.
POST /api/v1/trip-requests · operationId requestTrip
Submits a trip request into AtlasCare's staff review workflow. Every channel — AtlasCare's website, AI agents, API partners, and AtlasCare's phone agent — submits through this same service, which records one trip and sends every notification from it.
Include the quote_token from step 1 so the price shown to your user is the price AtlasCare reviews. A token is honored only when it verifies and was issued for the same price-relevant trip details (addresses, trip and return type, requested wait, mobility type, equipment). Otherwise the request is not rejected — it is priced at submission by the same evaluation /api/v1/trip-options performs, and the response says why in quote_token_issue (EXPIRED, INPUTS_CHANGED, BAD_SIGNATURE, MALFORMED). Availability, including the return leg, is always re-checked at submission.
Send an Idempotency-Key header to retry safely: a repeated key returns "duplicate": true with the same request_id instead of creating a second request or re-sending notifications.
source is required and must be one of: web_wizard, ai_agent, api_partner, facility_portal, phone_agent, staff. It costs nothing to send and tells AtlasCare staff whether a request came from a person or from something acting on a person's behalf — use ai_agent if that's you. The optional source_reference (up to 120 characters) carries your own identifier for the conversation or call that produced the request.
Required inputs: contact (first/last name and phone or email), pickup_address, destination_address, pickup_datetime and/or appointment_datetime (ISO 8601, future, see Date & Time Format below), mobility_type, and trip_type. return_type is required for a complete round-trip evaluation but its absence does not block submission — see Missing or Incomplete Inputs below.
Supported return arrangements (return_type, required when trip_type is round_trip): wait_and_return (vehicle and driver wait at the appointment — send the expected appointment length in requested_wait_minutes), scheduled_return (a separate pickup at a specific later time — send it in scheduled_return_time, or scheduled_return_datetime for a return on a different date), will_call (passenger calls when ready; return timing isn't known in advance). Each is checked as described in Round Trips & the Return Leg.
Authorization: AtlasCare does not currently gate standard trip-request submission behind an explicit authorization check — the source and requester fields identify who is submitting, and staff review every request before confirming. The one place an explicit authorization confirmation is required is a recurring-transportation request, where the wizard requires a checked attestation ("I confirm that I am authorized to request this recurring transportation...") before it will submit.
Text messages: preferred_contact: "text" is a preference, not permission. AtlasCare texts a number only after that person opts in to the AtlasCare SMS program themselves, on atlascaretransport.com or by phone with AtlasCare. API callers cannot give SMS consent for someone else, and an sms_consent field from an API caller is ignored. The response's sms_updates says which applies.
Booking boundaries: a successful response here means AtlasCare received and will review the request — never that transportation is booked. There is no endpoint that returns a confirmed reservation synchronously.
Example — synthetic data, not a real customer or request:
{
"contact": { "first_name": "Jordan", "last_name": "Lee", "phone": "+15035551234", "email": "jordan@example.com" },
"pickup_address": { "formatted": "2700 NW Stewart Pkwy, McMinnville, OR" },
"destination_address": { "formatted": "3181 SW Sam Jackson Park Rd, Portland, OR" },
"pickup_datetime": "2026-09-22T08:00:00-07:00",
"mobility_type": "wheelchair",
"trip_type": "round_trip",
"return_type": "wait_and_return",
"requested_wait_minutes": 90,
"broda_required": false,
"quote_token": "<quote.token from /api/v1/trip-options>",
"preferred_contact": "email",
"requester_type": "individual",
"source": "ai_agent"
}
{
"ok": true,
"request_id": "ATR-2026-482913",
"status": "received",
"quote_id": "ATQ-260922-0P2M",
"quote_status": "estimated",
"availability_status": "available",
"return_leg": { "status": "available", "reason_code": null, "message": "...", "estimated_return_datetime": "2026-09-22T18:49:00.000Z", "basis": "computed" },
"quote_source": "verified_token",
"quote_token_issue": null,
"message": "AtlasCare received this trip request. Submitting this request does not create a confirmed reservation...",
"status_url": "/api/v1/trip-requests/ATR-2026-482913/status"
}
GET /api/v1/trip-requests/{request_id}/status
Returns the current status of the request's trip record — no contact details or addresses. status is received (in review, not booked), quote_sent (AtlasCare sent a quote to the requester), booked (AtlasCare confirmed the trip), or cancelled; unknown means no record was found, and the response says what to do instead of returning a 404.
A round trip commits a vehicle for a span of time, so AtlasCare evaluates both ends of it. The return is judged against the same service hours and staff calendar windows as the pickup, and a staff window is tested against the whole time the vehicle is committed, not just the pickup instant. The overall availability.status already folds the return in (most restrictive wins); return_leg explains it:
| Field | Meaning |
|---|---|
status | available, limited, manual_review, unavailable, or unknown (the return could not be checked — most often a Scheduled Return with no time given). An unknown return never downgrades an otherwise good pickup. |
reason_code | RETURN_OUTSIDE_SERVICE_HOURS, RETURN_ON_CLOSED_DAY, RETURN_WINDOW_STAFF_OVERRIDE, RETURN_STAFF_OVERRIDE, RETURN_TIME_UNKNOWN, or null when the return is fine. |
estimated_return_datetime | When AtlasCare expects the vehicle to be free again. |
basis | How that time was arrived at: stated (the requester's own return time), computed (from the appointment length they gave plus routed drive time), assumed (AtlasCare's planning assumption — used for Will Call, which has no committed end time, and for a Wait & Return with no stated appointment length), or unknown. Never present assumed or unknown to a passenger as a confirmed return time. |
A return that falls outside service hours comes back as manual_review, not unavailable — AtlasCare can usually still arrange it after a quick conversation. Only a staff calendar window explicitly marked unavailable produces unavailable. For example, a Scheduled Return at 9:15 PM:
"availability": {
"status": "manual_review",
"label": "We’ll Confirm Availability",
"message": "The pickup time works. The return would fall outside the hours AtlasCare normally runs, so we’ll confirm the return before booking.",
"return_leg": {
"status": "manual_review",
"reason_code": "RETURN_OUTSIDE_SERVICE_HOURS",
"estimated_return_datetime": "2026-09-23T04:15:00.000Z",
"basis": "stated"
}
}
What an available result means. Staff mark a calendar window available only when a vehicle and driver can cover it, and both legs are checked against that calendar. It is not a live booking ledger: submitting a request does not hold capacity, so two requests can each be told the same window is available, and dates beyond the maintained calendar (about two weeks ahead) fall back to standard service hours. An available result is AtlasCare's expectation that it can serve the trip — staff confirmation is what makes it definite. This applies equally to one-way trips.
Send appointment_datetime when the passenger knows their appointment time. pickup_datetime becomes optional: without it, AtlasCare suggests a pickup from the routed drive time —
pickup = appointment − drive time − 15-minute arrival buffer − 15 minutes for each end with a transfer, rounded down to the nearest 5 minutes.
The buffers are published under rules in /api/v1/config. The response's schedule.pickup_basis says which case applies: stated (your pickup time), suggested (worked back from the appointment), or assumed (the drive time couldn't be calculated, so a 60-minute lead was used). Confirm a suggested or assumed pickup with the passenger. If you send both times, the pickup must be earlier, and schedule.pickup_may_be_late is true when it leaves less time than the suggestion.
"schedule": {
"pickup_datetime": "2026-09-22T16:05:00.000Z",
"pickup_basis": "suggested",
"appointment_datetime": "2026-09-22T17:00:00.000Z",
"suggested_pickup_datetime": "2026-09-22T16:05:00.000Z",
"suggestion_breakdown": { "drive_minutes": 38, "arrival_buffer_minutes": 15, "transfer_minutes": 0, "lead_minutes": 53 },
"pickup_may_be_late": false
}
transfer_at_pickup and transfer_at_destination (yes, no or unsure; default no) say whether the passenger must be transferred onto AtlasCare's chair at pickup, or off it at the destination. Transfers are completed by facility staff or the passenger's in-home caregiver — AtlasCare staff do not lift. AtlasCare adjusts the BRODA Traversa's height, tilt, recline and leg elevation so the transfer is a no-lift transfer.
yes at either end requires mobility_type: "wheelchair" and makes the BRODA Traversa and a transfer board required, whatever broda_required says. The BRODA Traversa equipment charge applies; the transfer board carries no charge.unsure transfer makes both unsure and routes the quote to manual_review.Send pickup_location_type and destination_location_type (facility, residence or other), and for each end with a transfer, transfer_assist_at_pickup / transfer_assist_at_destination:
| Value | Meaning and outcome |
|---|---|
facility_staff | Staff at a facility complete the transfer. Default when the location type is facility. |
in_home_caregiver | The passenger's caregiver completes it at a home. Default when the location type is residence. Also send transfer_assistant_name_at_…, transfer_assistant_phone_at_… and transfer_assist_confirmed_at_…: true once the requester confirms the caregiver will be there. Unconfirmed is accepted but flagged for review. |
none_available | No one can complete the transfer. Accepted, but flagged high risk; AtlasCare will call the requester before scheduling. AtlasCare's own website asks the person to call instead. |
unsure | Not yet known — the default when no location type is given. Flagged for review. |
On a round trip each transfer happens twice: the caregiver at a home pickup must also be there when the passenger is brought back, and destination staff are needed again for the return. Tell an in-home caregiver the estimated return time from availability.return_leg (or your stated return time plus the drive), and say it is an estimate — or, for Will Call, that there is no set time and the driver will call ahead.
"equipment": {
"broda_traversa": "yes",
"transfer_board": "yes",
"transfer_at_pickup": "yes",
"transfer_at_destination": "no",
"reasons": ["transfer_at_pickup"],
"transfer_note": "Transfers are completed by facility staff. AtlasCare brings the BRODA Traversa and a transfer board and adjusts the chair’s height, tilt, recline and leg elevation for a no-lift transfer."
}
For wheelchair trips, REQUEST_TRIP also accepts own_wheelchair (yes/no), wheelchair_type (manual, power, transport, other_not_sure) and weight_range (under_250, over_250, not_sure; over_250 is bariatric and the trip is held for staff review), which AtlasCare uses to confirm vehicle and equipment capacity.
Use these only when you need one answer without the other. Both are built from the same pricing and availability rules as /api/v1/trip-options.
POST /api/v1/availability · operationId checkAvailability
Whether AtlasCare appears able to serve a requested pickup window, without calculating a price. Send trip_type: "round_trip" with the return fields to have the return leg checked too. No drive time is calculated here, so a Wait & Return or Will Call return is estimated from the trip's own timings and reported with basis: "assumed" — use /api/v1/trip-options to judge the return against real drive time.
{
"pickup_datetime": "2026-09-22T08:00:00-07:00",
"trip_type": "round_trip",
"return_type": "scheduled_return",
"scheduled_return_time": "15:30"
}
{
"status": "available",
"label": "Available",
"message": "AtlasCare currently has availability for this trip.",
"requested_datetime": "2026-09-22T08:00:00-07:00",
"return_leg": { "status": "available", "reason_code": null, "message": "...", "estimated_return_datetime": "2026-09-22T22:30:00.000Z", "basis": "stated" }
}
POST /api/v1/quote · operationId getPrice
Pricing only — no availability check. Same request shape as /api/v1/trip-options; returns the quote object on its own (id, token, status, total, and the same pricing detail). Its token can be passed to REQUEST_TRIP under the same rules.
GET /api/v1/config
The same posted pricing tiers, Wait & Return rates, equipment charges, service hours, and return-leg timing assumptions used by the API — safe to read directly instead of hard-coding AtlasCare's rates into your own system.
Send pickup_datetime and appointment_datetime (and scheduled_return_datetime, when used) as ISO 8601 with an explicit UTC offset, e.g. 2026-09-15T08:00:00-07:00. AtlasCare's service area and operating hours are defined in the America/Los_Angeles time zone; include the correct offset for that zone (-07:00 during Pacific Daylight Time, -08:00 during Pacific Standard Time) rather than assuming UTC.
A request to /api/v1/trip-options or /api/v1/trip-requests that is missing a required field (pickup_address, destination_address, both pickup_datetime and appointment_datetime, mobility_type, or trip_type) is rejected with a 400 before any availability or pricing check runs:
{
"ok": false,
"error": "This trip request is missing required details: pickup_address is required. mobility_type must be one of: wheelchair, ambulatory, not_sure.",
"reason_code": "VALIDATION_FAILED"
}
The error string always spells out exactly which fields are missing or invalid — a caller (human or agent) can ask for those specific details and resubmit rather than guessing. return_type is the one exception: a round trip submitted without it is not rejected — it is priced with quote.status: "manual_review" so AtlasCare can confirm the return arrangement before finalizing.
| HTTP status | reason_code | Meaning |
|---|---|---|
| 400 | VALIDATION_FAILED | One or more required fields are missing or malformed; error lists which. |
| 400 | MISSING_FIELD | A single required field (e.g. pickup_datetime on /api/v1/availability) was not sent. |
| 400 | INVALID_DATETIME | pickup_datetime could not be parsed as ISO 8601. |
| 400 | PAST_DATETIME | The requested pickup date/time is in the past. |
| 401 | UNAUTHENTICATED | A trusted source (api_partner, phone_agent, facility_portal, staff) was used without an API key — see Authentication. |
| 401 | INVALID_API_KEY | An Authorization header was sent, but the key is not recognized (revoked or mistyped). |
| 403 | SOURCE_NOT_ALLOWED | The API key is valid, but that client may not submit with this source. |
| 413 | PAYLOAD_TOO_LARGE | Request body exceeded the size limit. |
| 429 | RATE_LIMITED | Rate limit exceeded (per IP, or per client for a keyed request) — see Rate Limiting & Fair Use; back off for the seconds given in Retry-After. |
| 500 | — | An unexpected server error. On /api/v1/availability and /api/v1/trip-options, an internal failure in the availability check itself does not surface as a 500 or as unavailable — it degrades to a 200 response with status: "manual_review", so a transient technical failure is never presented as a confirmed lack of availability. |
| Status | Meaning |
|---|---|
available | Capacity currently appears open for this window. |
limited | Capacity may be available; AtlasCare will confirm the best pickup time. |
manual_review | Needs a quick scheduling review — not a failure state. |
unavailable | Not available at the requested time; try another time or submit for review. |
| Status | Meaning |
|---|---|
estimated | Calculated from AtlasCare's standard posted pricing rules. |
manual_review | One or more trip details need a human to confirm pricing (e.g. special equipment, unusual mileage, an incomplete return arrangement). Not a failure — still a valid, expected outcome. |
confirmed | Reserved for a future state once AtlasCare has explicitly confirmed a price with the customer. |
expired | The quote token's validity window has passed; request a new quote. |
These endpoints sit behind Cloudflare's network-level protections, plus a per-IP application-level limit with a numeric, machine-readable contract so an integration can self-throttle predictably instead of guessing:
| Bucket | Endpoints | Limit |
|---|---|---|
| Lookup | /api/v1/availability, /api/v1/quote, /api/v1/trip-options | 30 requests / 60s per IP |
| Submit | /api/v1/trip-requests | 10 requests / 60s per IP |
| Read | /api/v1/config, /api/v1/openapi.json, /api/v1/trip-requests/{id}/status | 60 requests / 60s per IP |
Requests with an API key are counted per client, not per IP, against limits agreed with that client (for example, a phone agent making calls from shared servers). Unrecognized keys count against the caller's IP.
Every response from these endpoints carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (seconds until the window resets) — check these instead of waiting to get cut off. Exceeding the limit gets a 429 with a Retry-After header (seconds to wait) and reason_code: RATE_LIMITED; back off for that long and retry. These numbers are also published live at /api/v1/config under rate_limits, so an integration can read the current limits instead of hard-coding them. Please also cache /api/v1/config and /api/v1/openapi.json (they change rarely) rather than relying on the rate limit alone.
For an integration that wants a short, machine-readable summary rather than parsing this page or the full OpenAPI document, AtlasCare publishes a custom /developers/capabilities.json — the AtlasCare capability manifest. It is not a universal discovery standard; it's a small AtlasCare-specific pointer to the same OpenAPI operations documented above, plus the plain-language limitations already described on this page.