{"components":{"parameters":{"AgentClient":{"description":"Optional self-reported client name, recorded as unverified. Kept only when it is 1–64\nprintable ASCII characters; otherwise ignored. It never changes authorization or results.\n","in":"header","name":"X-Agent-Client","required":false,"schema":{"maxLength":64,"type":"string"}},"CarAlias":{"in":"path","name":"alias","required":true,"schema":{"examples":["Los_Angeles_Tesla_Model_3_2018_US1L1"],"type":"string"}},"IdempotencyKey":{"description":"Required for API-key create and cancel. A freshly generated UUID v4 per new command; reuse\nit unchanged for retries of that command. 16–128 printable ASCII characters. A retry of a\ncompleted command returns the original status and body; the same key with a different body\nor reservation is 409 `idempotency_mismatch`. Completed results are kept permanently.\n","in":"header","name":"Idempotency-Key","required":true,"schema":{"maxLength":128,"minLength":16,"type":"string"}},"ReservationUUID":{"in":"path","name":"uuid","required":true,"schema":{"format":"uuid","type":"string"}}},"responses":{"Conflict":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"`idempotency_mismatch`: the same Idempotency-Key was used for a different command.\n`operation_in_progress`: retry the same command with the same key after `Retry-After` (2 s).\nBusiness conflicts (overlapping dates, `active_reservation_exists`) also use 409.\n","headers":{"Retry-After":{"schema":{"minimum":1,"type":"integer"}}}},"Forbidden":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Authenticated but not allowed. `api_key_write_upgrade_required`: the key is `read_only`;\nthe customer creates a `booking_write` key in settings (the settings URL is in\n`description`). `api_key_operation_not_enabled`: the operation is not available to keys yet.\n"},"ManualAction":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/ManualAction"}},"required":["data"],"type":"object"}}},"description":"A link the customer opens and confirms. Nothing was executed."},"NotFound":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No such reservation or invoice for this customer."},"RateLimited":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded. Retry after `Retry-After` seconds.","headers":{"Retry-After":{"schema":{"minimum":1,"type":"integer"}}}},"Unauthorized":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid or revoked credentials (`invalid_credentials`), or more than one credential\nheader (`conflicting_credentials`).\n"},"Unavailable":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"`operation_outcome_unknown`: the commit result is unknown; retry with the SAME key.\n`authentication_unavailable`: key verification is busy or unavailable (`Retry-After: 1`).\n`rate_limit_unavailable`: the key's rate counter is unavailable; the call was not executed\n(`Retry-After: 1`).\n`manual_action_unavailable`: the link could not be recorded, so none was returned\n(`Retry-After: 1`).\n","headers":{"Retry-After":{"schema":{"minimum":1,"type":"integer"}}}}},"schemas":{"CancellationOutcome":{"description":"Read from local records only. `cancelled` does not mean money was returned. `hold_release`,\n`refund_review` and `refunds` are present only when `status` is `cancelled`. `unknown` means the\nrecords cannot establish the answer (for example a cancellation recorded before this field existed).\n","properties":{"hold_release":{"properties":{"status":{"enum":["not_required","pending","released","manual_review","unknown"],"type":"string"}},"type":"object"},"refund_review":{"properties":{"status":{"enum":["not_required","pending","closed","unknown"],"type":"string"}},"type":"object"},"refunds":{"description":"Known refund receipts. Empty means none known, not that none is owed.","items":{"properties":{"amount_cents":{"type":"integer"},"confirmed_at":{"type":["string","null"]},"id":{"description":"Opaque Carsan refund record id. Never a provider id.","type":"string"},"status":{"enum":["confirmed","recorded_unconfirmed","failed","unknown"],"type":"string"}},"type":"object"},"type":"array"},"status":{"enum":["not_cancelled","cancelled","unknown"],"type":"string"}},"required":["status"],"type":"object"},"Car":{"description":"Customer-safe car fields. No plate and no base daily rate.","properties":{"address":{"type":["string","null"]},"area":{"type":["string","null"]},"blended_day_rate_cents":{"type":"integer"},"blocked_ranges":{"description":"Car-local ranges that cannot be booked (detail only). `to` null means open-ended.","items":{"properties":{"from":{"type":"string"},"kind":{"type":"string"},"to":{"type":["string","null"]}},"type":"object"},"type":"array"},"body_type":{"type":["string","null"]},"car_alias":{"type":"string"},"car_id":{"type":"integer"},"city":{"enum":["la","miami"],"type":"string"},"date_next_block":{"type":["string","null"]},"description":{"type":"string"},"discounted_day_rate_cents":{"type":"integer"},"display_trip_total_before_discount_cents":{"type":"integer"},"display_trip_total_cents":{"description":"Rent plus trip fee for the searched dates.","type":"integer"},"doors":{"type":"integer"},"insurance_coverage_usd":{"description":"Whole US dollars.","type":["integer","null"]},"is_available":{"description":"Present only when dates were searched.","type":"boolean"},"is_hot_deal":{"type":"boolean"},"make":{"type":"string"},"model":{"type":"string"},"mpg":{"type":["integer","null"]},"name":{"type":"string"},"photos":{"items":{"format":"uri","type":"string"},"type":"array"},"power_type":{"type":"string"},"previews":{"items":{"type":"string"},"type":"array"},"prices":{"$ref":"#/components/schemas/CarPrices"},"rent_trip_savings_cents":{"type":"integer"},"rent_trip_total_cents":{"description":"Rent only, after duration discount, for the searched dates.","type":"integer"},"seats":{"type":"integer"},"state":{"type":["string","null"]},"trip_days":{"type":"integer"},"year":{"type":"string"},"zip_code":{"type":["string","null"]}},"required":["car_alias","name","prices"],"type":"object"},"CarPrices":{"description":"Integer USD cents unless named otherwise. No base daily rent rate.","properties":{"car":{"properties":{"miles_included":{"type":"integer"},"min_age":{"type":"integer"},"min_age_without_young_driver_fee":{"type":"integer"},"price_delivery":{"type":"integer"},"price_deposit":{"description":"Deposit in cents.","type":"integer"},"price_extra_mile":{"type":"integer"},"price_unlimited_mileage":{"type":"integer"}},"type":"object"},"extras":{"items":{"properties":{"item_type":{"type":"string"},"price_day":{"type":"integer"},"title":{"type":"string"}},"type":"object"},"type":"array"},"protection":{"additionalProperties":{"type":"integer"},"description":"Per-day price by protection plan (`minimum`, `standard`).","type":"object"},"trip_fee":{"type":"integer"}},"type":"object"},"Card":{"properties":{"card_brand":{"type":"string"},"exp_month":{"maximum":12,"minimum":1,"type":"integer"},"exp_year":{"type":"integer"},"id":{"type":"string"},"last4":{"pattern":"^\\d{4}$","type":"string"}},"required":["id","last4","card_brand","exp_month","exp_year"],"type":"object"},"CarsPage":{"properties":{"cars":{"items":{"$ref":"#/components/schemas/Car"},"type":"array"},"has_more":{"type":"boolean"},"total":{"description":"Matching cars before pagination.","type":"integer"}},"required":["cars","total","has_more"],"type":"object"},"Error":{"properties":{"description":{"type":"string"},"error":{"description":"Human-readable message.","type":"string"},"error_code":{"$ref":"#/components/schemas/ErrorCode"},"request_id":{"type":"string"}},"required":["error"],"type":"object"},"ErrorCode":{"anyOf":[{"oneOf":[{"const":"rate_limited","description":"Phase 1. The applicable rate budget is exhausted; wait Retry-After."},{"const":"invalid_credentials","description":"Invalid, revoked or inactive credential."},{"const":"conflicting_credentials","description":"More than one credential header was sent."},{"const":"api_key_operation_not_enabled","description":"The operation is not available to API keys yet."},{"const":"authentication_unavailable","description":"Key verification busy or unavailable; wait Retry-After."},{"const":"rate_limit_unavailable","description":"Key rate counter unavailable; the call was not executed."},{"const":"invalid_pagination","description":"Phase 1. limit outside 1..200."},{"const":"date_range_incomplete","description":"Phase 1. Only one of date_from/date_to was sent."},{"const":"invalid_date_format","description":"Phase 1. A date is not YYYY-MM-DDTHH:MM."},{"const":"invalid_date_range","description":"Phase 1. date_to is not after date_from."},{"const":"promo_codes_disabled","description":"Phase 1. Promo codes are off."},{"const":"promo_code_not_found","description":"Phase 1. Unknown promo code."},{"const":"promo_code_invalid","description":"Phase 1. Promo code cannot be applied."},{"const":"promo_already_used","description":"Phase 1. One-time promo already used by this customer."},{"const":"active_reservation_exists","description":"Existing. The customer already has the maximum active reservations."},{"const":"api_key_write_upgrade_required","description":"The key is read_only; the customer creates a booking_write key in settings."},{"const":"reservation_not_found","description":"No such reservation for this customer."},{"const":"invalid_reservation_id","description":"The reservation id is not a UUID."},{"const":"invalid_request_body","description":"The JSON body could not be read."},{"const":"invalid_payment_type","description":"payment_type is not rent or deposit."},{"const":"nothing_to_pay","description":"No unpaid invoice of that payment type for this customer."},{"const":"reservation_cancelled","description":"The reservation is cancelled."},{"const":"reservation_not_active","description":"Only a new (not complete or cancelled) reservation can be extended."},{"const":"invalid_checkout","description":"Extension target is malformed, in the past, or not later than the current checkout."},{"const":"card_payments_not_enabled","description":"Card payments are not enabled for this account yet."},{"const":"manual_action_unavailable","description":"The link could not be issued; retry after Retry-After."},{"const":"idempotency_key_required","description":"Phase 3. Key create/cancel sent without Idempotency-Key."},{"const":"idempotency_key_invalid","description":"Phase 3. Idempotency-Key is not 16-128 printable ASCII."},{"const":"idempotency_mismatch","description":"Phase 3. Same key, different command."},{"const":"operation_in_progress","description":"Phase 3. Retry the same command and key."},{"const":"operation_outcome_unknown","description":"Phase 3. Commit result unknown; retry with the same key."}]},{"type":"string"}],"description":"Stable machine-readable codes an agent can branch on. Other existing codes may appear."},"FinancialSummary":{"description":"Current persisted state, not a final cost guarantee, and not a payment state. Integer USD cents.\n","properties":{"currency":{"const":"USD","type":"string"},"deposit_cents":{"description":"Deposit required by the booking. Does not say whether it was held, charged, released or refunded.","type":["integer","null"]},"trip_total_cents":{"description":"Trip cost after discounts, applied extensions, fees and adjustments, without the deposit.\nIndependent of balance. `null` when the trip's billing records cannot be classified\n(for example a paid trip that was cancelled, or a manual adjustment); never an invented zero.\n","type":["integer","null"]}},"required":["currency","trip_total_cents","deposit_cents"],"type":"object"},"Invoice":{"additionalProperties":true,"properties":{"amount":{"description":"Integer USD cents, in the ledger sign convention: charges against the customer can be negative.","type":"integer"},"billing_status":{"description":"Actual persisted invoice state. HOLD is a card authorization, not a charge.","enum":["ISSUED","PAID","CANCELLED","HOLD"],"type":"string"},"created_at":{"description":"Creation time, UTC, YYYY-MM-DDTHH:MM.","type":"string"},"currency":{"const":"USD","type":"string"},"description":{"type":"string"},"id":{"format":"uuid","type":"string"},"items":{"items":{"properties":{"amount":{"description":"Integer USD cents; discounts are negative.","type":"integer"},"description":{"type":"string"},"id":{"format":"uuid","type":"string"}},"type":"object"},"type":"array"},"status":{"description":"Legacy field. On the reservation detail a HOLD shows as PAID; use `billing_status`.","enum":["ISSUED","PAID","CANCELLED","HOLD"],"type":"string"},"type":{"description":"Billing type, for example RENT, DEPOSIT, EXTEND, FEE_RENT, REFUND, DEBT.","type":"string"}},"required":["id","created_at","currency","type","status","billing_status","amount","description","items"],"type":"object"},"ManualAction":{"properties":{"action":{"enum":["pay_reservation","add_payment_card","extend_reservation"],"type":"string"},"agent_flow_id":{"description":"Correlation id of this handoff, also carried in `url`. Not a token and not an authority;\nthe customer still logs in and confirms. Read the account again to learn the outcome.\n","format":"uuid","type":"string"},"status":{"const":"requires_user_action","type":"string"},"url":{"description":"A Carsan page. Contains no key, token or payment secret, and authorizes nothing.","examples":["https://app.carsan.com/trips/EXAMPLE_UUID?intent=pay\u0026payment_type=reservation\u0026agent_flow_id=EXAMPLE_FLOW_UUID"],"format":"uri","type":"string"}},"required":["action","status","url","agent_flow_id"],"type":"object"},"PaymentStatus":{"properties":{"amount":{"description":"Integer USD cents. Omitted when settled.","type":"integer"},"date":{"description":"refund only: expected credit/return date, car-local YYYY-MM-DD.","type":"string"},"invoice_id":{"description":"to_pay only: the payable invoice to pay.","format":"uuid","type":"string"},"type":{"enum":["settled","to_pay","refund"],"type":"string"}},"required":["type"],"type":"object"},"Quote":{"description":"Integer USD cents. `final_total` = `display_total` = `display_trip_total` is the selected-options\ntrip price without the deposit. `deposit_cents` is separate.\n","properties":{"blended_day_rate":{"type":"integer"},"delivery_total":{"type":"integer"},"deposit_cents":{"description":"Refundable deposit","not included in any total.":null,"type":"integer"},"discounted_day_rate":{"type":"integer"},"display_mode":{"const":"trip_total","type":"string"},"display_total":{"type":"integer"},"display_trip_total":{"type":"integer"},"extras_total":{"type":"integer"},"final_total":{"type":"integer"},"promo_discount_amount":{"type":"integer"},"protection_total":{"type":"integer"},"rent_discount_amount":{"type":"integer"},"rent_subtotal":{"type":"integer"},"trip_fee_total":{"type":"integer"},"unlimited_mileage_total":{"type":"integer"}},"required":["rent_subtotal","rent_discount_amount","protection_total","trip_fee_total","final_total","display_total","display_mode","blended_day_rate","display_trip_total","discounted_day_rate","deposit_cents"],"type":"object"},"QuoteRequest":{"properties":{"car_alias":{"type":"string"},"date_checkin":{"examples":["2026-10-01T10:00"],"pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}$","type":"string"},"date_checkout":{"examples":["2026-10-04T10:00"],"pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}$","type":"string"},"extras":{"items":{"type":"string"},"type":"array"},"options":{"$ref":"#/components/schemas/ReservationOptions"},"promo_code":{"type":"string"}},"required":["car_alias","date_checkin","date_checkout"],"type":"object"},"ReservationCreateRequest":{"allOf":[{"$ref":"#/components/schemas/QuoteRequest"},{"properties":{"options":{"allOf":[{"$ref":"#/components/schemas/ReservationOptions"},{"required":["protection_plan","mileage_type","delivery_type"]}]}},"required":["options"],"type":"object"}]},"ReservationOptions":{"properties":{"delivery_address":{"description":"Required when delivery_type is delivery.","type":["string","null"]},"delivery_type":{"default":"pickup","enum":["pickup","delivery"],"type":"string"},"mileage_type":{"default":"limited","enum":["limited","unlimited"],"type":"string"},"protection_plan":{"default":"minimum","enum":["minimum","standard"],"type":"string"}},"type":"object"},"Trip":{"additionalProperties":true,"description":"Existing reservation fields plus the additive projections below. `financial_summary` is on the\ntrips list and the detail; `payment_status`, `invoices` and `cancellation_outcome` are on the\ndetail only.\n","properties":{"balance_cents":{"type":"integer"},"cancellation_outcome":{"$ref":"#/components/schemas/CancellationOutcome"},"car":{"$ref":"#/components/schemas/Car"},"date_checkin":{"description":"Car-local.","type":"string"},"date_checkout":{"description":"Car-local.","type":"string"},"days":{"type":"integer"},"financial_summary":{"$ref":"#/components/schemas/FinancialSummary"},"invoices":{"items":{"$ref":"#/components/schemas/Invoice"},"type":"array"},"payment_status":{"$ref":"#/components/schemas/PaymentStatus"},"status":{"type":"string"},"uuid":{"format":"uuid","type":"string"}},"type":"object"},"VerificationStatus":{"properties":{"drivers_license":{"properties":{"expired":{"type":"boolean"},"expires_at":{"description":"YYYY-MM-DD.","type":["string","null"]},"expiring_soon":{"description":"Expires within 30 days.","type":"boolean"},"status":{"enum":["unknown","pending","approved","declined"],"type":"string"}},"required":["status","expires_at","expired","expiring_soon"],"type":"object"},"is_approved_to_drive":{"type":"boolean"},"status":{"description":"`verified`: approved to drive. `pending`: a driver's-licence submission awaits a decision.\n`unknown`: anything else. A manager's decision is never disclosed.\n","enum":["unknown","pending","verified"],"type":"string"}},"required":["status","is_approved_to_drive","drivers_license"],"type":"object"}},"securitySchemes":{"carsanKeyBearer":{"bearerFormat":"carsan_...","description":"A customer API key created manually in Carsan settings: `Authorization: Bearer carsan_...`.\nKeys never authorize payment, card changes, KYC, extension execution or key management.\nThe Carsan app's own login token is also accepted on the same operations.\nSend exactly one credential; conflicting credential headers are rejected.\n","scheme":"bearer","type":"http"},"carsanKeyHeader":{"description":"The same customer API key in the `X-API-Key` header.","in":"header","name":"X-API-Key","type":"apiKey"}}},"info":{"contact":{"name":"Carsan","url":"https://app.carsan.com/agents"},"description":"One API for the Carsan app and for AI agents acting for a customer.\n\n**Available now (Phase 1):** car search, car detail, date availability and price quotes. No\naccount and no key. Send no credentials on these calls.\n\n**Planned (Phase 2 and 3):** operations marked `x-carsan-availability: planned` are specified\nhere but are not deployed for agents yet. Do not rely on them until they are marked available.\n`x-carsan-key-enabled: true` records that the build accepts a customer key on the operation.\n\n**Customer-only actions.** Signup, identity verification (KYC), payment, adding a card and\nexecuting an extension are never done through the API. The API returns a Carsan URL\n(`requires_user_action`); the customer opens it, reviews and confirms. Read the account or\nreservation again to learn the real outcome. A generated link or a visited page is not\ncompletion.\n\n**Money.** Amounts are integer US cents, including quote fields without a `_cents` suffix.\nFields ending in `_usd` are whole dollars.\n\n**Dates.** Search, quote and reservation dates are car-local wall-clock strings\n`YYYY-MM-DDTHH:MM`. Do not convert them to UTC. City time zones: `la` → `America/Los_Angeles`,\n`miami` → `America/New_York`.\n\n**Rate limits.** Anonymous catalog calls (car list, car detail, credential-free quotes and this\ndocument) share a per-IP budget per API instance; other anonymous and app calls use a general\nper-IP budget. A call with a valid customer key uses that key's own budget, shared by all API\ninstances and counted in fixed UTC-minute windows (so a burst can straddle a window boundary).\nA call with an invalid key spends the caller IP's general budget. Budgets are not published yet.\nOn 429 or 503, wait the number of seconds in `Retry-After`.\n\n**Guarantees.** A quote does not reserve a car or fix a price. Creation and manual payment\nrevalidate current price, eligibility and availability. An unpaid reservation is not a paid\nbooking or a guaranteed calendar hold.\n","summary":"Car search, prices and customer account actions for AI agents and the Carsan app.","title":"Carsan customer and agent API","version":"1.0.0-phase1"},"openapi":"3.1.0","paths":{"/cars":{"get":{"description":"Lists cars, optionally for a date range. Anonymous; do not send credentials.\nWith `date_from` and `date_to`, each car gets `is_available` and date-based totals\n(`rent_trip_total_cents`, `display_trip_total_cents`). Without dates the list shows no totals.\nPage with `offset` until `has_more` is false.\n","operationId":"listCars","parameters":[{"in":"query","name":"city","schema":{"enum":["la","miami"],"type":"string"}},{"description":"Car-local start `YYYY-MM-DDTHH:MM`. Must be sent together with `date_to`.","in":"query","name":"date_from","schema":{"examples":["2026-10-01T10:00"],"pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}$","type":"string"}},{"description":"Car-local end `YYYY-MM-DDTHH:MM`, after `date_from`. Must be sent together with `date_from`.","in":"query","name":"date_to","schema":{"examples":["2026-10-04T10:00"],"pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}$","type":"string"}},{"in":"query","name":"limit","schema":{"default":50,"maximum":200,"minimum":1,"type":"integer"}},{"in":"query","name":"offset","schema":{"default":0,"minimum":0,"type":"integer"}},{"in":"query","name":"body_type","schema":{"enum":["sedan","coupe","suv","hatchback","convertible","pickup","minivan","three-wheeler","other"],"type":"string"}},{"in":"query","name":"make_id","schema":{"minimum":0,"type":"integer"}},{"in":"query","name":"model_id","schema":{"minimum":0,"type":"integer"}},{"in":"query","name":"order_by","schema":{"enum":["price_asc","price_desc"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/CarsPage"}},"required":["data"],"type":"object"}}},"description":"Cars for the request."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid query. `error_code` is one of `invalid_pagination`, `date_range_incomplete`,\n`invalid_date_format`, `invalid_date_range`.\n"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[],"summary":"Search cars","tags":["cars"],"x-carsan-availability":"available","x-carsan-phase":1}},"/cars/{alias}":{"get":{"description":"Anonymous; do not send credentials. `blocked_ranges` are car-local times that cannot be booked.","operationId":"getCar","parameters":[{"$ref":"#/components/parameters/CarAlias"}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Car"}},"required":["data"],"type":"object"}}},"description":"The car."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No such car."},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[],"summary":"Car detail and booked ranges","tags":["cars"],"x-carsan-availability":"available","x-carsan-phase":1}},"/my/billing/cards":{"get":{"description":"Zero or one card: the newest/default saved card, the card a charge would use. No provider\ncall, no card check or change. A saved card does not guarantee a future payment succeeds.\n","operationId":"listCards","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Card"},"maxItems":1,"type":"array"}},"required":["data"],"type":"object"}}},"description":"Masked cards."},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"carsanKeyBearer":[]},{"carsanKeyHeader":[]}],"summary":"Saved card metadata (read-only)","tags":["account"],"x-carsan-availability":"planned","x-carsan-key-capability":"read_only","x-carsan-key-enabled":true,"x-carsan-phase":2}},"/my/billing/cards/add-link":{"post":{"description":"Returns a Carsan URL. No card, Stripe customer or SetupIntent is created. With no saved card\nthe URL is the card-entry page (`/billing/card-add`); with a saved card it is the saved-card\npage (`/billing/cards`), where the customer reviews the current card and chooses to replace\nit. `card_payments_not_enabled` (403): card payments are not enabled for this account yet.\n","operationId":"getAddCardLink","parameters":[{"$ref":"#/components/parameters/AgentClient"}],"responses":{"200":{"$ref":"#/components/responses/ManualAction"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/Unavailable"}},"security":[{"carsanKeyBearer":[]},{"carsanKeyHeader":[]}],"summary":"Link for the customer to add a card","tags":["manual-actions"],"x-carsan-availability":"planned","x-carsan-key-capability":"read_only","x-carsan-key-enabled":true,"x-carsan-phase":2}},"/my/billing/invoice/{uuid}":{"get":{"description":"The same fields as the trip invoice list. Another customer's invoice is a 404.","operationId":"getInvoice","parameters":[{"in":"path","name":"uuid","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Invoice"}},"required":["data"],"type":"object"}}},"description":"The invoice."},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"carsanKeyBearer":[]},{"carsanKeyHeader":[]}],"summary":"Own invoice detail","tags":["reservations"],"x-carsan-availability":"planned","x-carsan-key-capability":"read_only","x-carsan-key-enabled":true,"x-carsan-phase":2}},"/my/billing/reservation/{uuid}/extension/price":{"post":{"description":"Computes the price of moving checkout. Changes no dates, charges nothing and makes no provider\ncall. Only for an own reservation in `new` status; another customer's reservation is a 404.\n","operationId":"getExtensionPrice","parameters":[{"$ref":"#/components/parameters/ReservationUUID"}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"modification_type":{"enum":["extend"],"type":"string"},"new_checkout_date_time_local":{"examples":["2026-10-06T10:00"],"type":"string"}},"required":["modification_type","new_checkout_date_time_local"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"additionalProperties":true,"type":"object"}},"required":["data"],"type":"object"}}},"description":"The price preview in integer USD cents."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid dates or the reservation cannot be extended."},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"carsanKeyBearer":[]},{"carsanKeyHeader":[]}],"summary":"Extension price preview (read-only)","tags":["manual-actions"],"x-carsan-availability":"planned","x-carsan-key-capability":"read_only","x-carsan-key-enabled":true,"x-carsan-phase":2}},"/my/profile":{"get":{"description":"The same schema for app tokens and keys. `payment_methods` is the same zero-or-one card as\n`/my/billing/cards`. No provider secret, raw document link, manager note or manager decision.\n","operationId":"getProfile","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"additionalProperties":true,"type":"object"}},"required":["data"],"type":"object"}}},"description":"The profile. `payment_methods` shows the same zero-or-one card as `/my/billing/cards`."},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/Unavailable"}},"security":[{"carsanKeyBearer":[]},{"carsanKeyHeader":[]}],"summary":"Own profile","tags":["account"],"x-carsan-availability":"planned","x-carsan-key-capability":"read_only","x-carsan-key-enabled":true,"x-carsan-phase":2}},"/my/reservation":{"post":{"description":"Creates a real unpaid reservation under the normal rules and returns its UUID. Payment is a\nseparate customer action (`payment-link`). Send a fresh UUID v4 `Idempotency-Key` per new\ncommand and reuse it unchanged for retries of that command.\n","operationId":"createReservation","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReservationCreateRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"format":"uuid","type":"string"}},"required":["data"],"type":"object"}}},"description":"The new reservation UUID."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid input or dates. `idempotency_key_required` (API key without the header) and\n`idempotency_key_invalid` (not 16–128 printable ASCII) are also 400.\n"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/Unavailable"}},"security":[{"carsanKeyBearer":[]},{"carsanKeyHeader":[]}],"summary":"Create an unpaid reservation","tags":["reservations"],"x-carsan-availability":"planned","x-carsan-key-capability":"booking_write","x-carsan-key-enabled":true,"x-carsan-phase":3}},"/my/reservation/{uuid}":{"delete":{"description":"Cancels under the normal eligibility and fee rules. A paid cancellation can create a fee,\nrelease a deposit hold or open a refund review. `OK` means the cancellation committed; read\n`cancellation_outcome` for hold and refund state. Send a fresh UUID v4 `Idempotency-Key`\nand reuse it for retries.\n","operationId":"cancelReservation","parameters":[{"$ref":"#/components/parameters/ReservationUUID"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"const":"OK","type":"string"}},"required":["data"],"type":"object"}}},"description":"Cancellation committed."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The reservation cannot be cancelled in its current state, or the Idempotency-Key is\nmissing (`idempotency_key_required`) or malformed (`idempotency_key_invalid`). An unknown\nor foreign reservation is always 404, whatever its status.\n"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/Unavailable"}},"security":[{"carsanKeyBearer":[]},{"carsanKeyHeader":[]}],"summary":"Cancel own reservation","tags":["reservations"],"x-carsan-availability":"planned","x-carsan-key-capability":"booking_write","x-carsan-key-enabled":true,"x-carsan-phase":3},"get":{"description":"Current amounts, payment state, `financial_summary` and `cancellation_outcome`. When the\ncustomer owes money, reading the reservation prepares the payable debt invoice (the same\nbehavior as the Carsan app), so `payment_status.invoice_id` is set on `to_pay`. In\n`invoices[]`, `status` keeps the app's legacy display (a HOLD shows as PAID); use\n`billing_status` for the actual invoice state.\n","operationId":"getReservation","parameters":[{"$ref":"#/components/parameters/ReservationUUID"}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Trip"}},"required":["data"],"type":"object"}}},"description":"The reservation."},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"carsanKeyBearer":[]},{"carsanKeyHeader":[]}],"summary":"Own reservation detail","tags":["reservations"],"x-carsan-availability":"planned","x-carsan-key-capability":"read_only","x-carsan-key-enabled":true,"x-carsan-phase":2}},"/my/reservation/{uuid}/extension-link":{"post":{"description":"Returns a Carsan URL (`/trips/{uuid}/modify`, plus `checkout` when a target is sent). Dates do\nnot change until the customer confirms, including for a zero-cost extension. The page fetches\nthe current quote; the target is only its initial value.\nRefusals: `reservation_not_active` (400) — only a `new` reservation can be extended;\n`invalid_checkout` (400) — malformed, in the past, or not later than the current checkout.\n","operationId":"getExtensionLink","parameters":[{"$ref":"#/components/parameters/ReservationUUID"},{"$ref":"#/components/parameters/AgentClient"}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"checkout":{"description":"Optional car-local target checkout `YYYY-MM-DDTHH:MM`.","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}$","type":"string"}},"type":"object"}}}},"responses":{"200":{"$ref":"#/components/responses/ManualAction"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"`reservation_not_active`, `invalid_checkout`, `invalid_request_body` or `invalid_reservation_id`."},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/Unavailable"}},"security":[{"carsanKeyBearer":[]},{"carsanKeyHeader":[]}],"summary":"Link for the customer to extend","tags":["manual-actions"],"x-carsan-availability":"planned","x-carsan-key-capability":"read_only","x-carsan-key-enabled":true,"x-carsan-phase":2}},"/my/reservation/{uuid}/invoices":{"get":{"description":"Every invoice of this customer on the trip, across types and states, with line items. An\nempty array is a valid result. Reading never creates, cancels or repairs an invoice.\n","operationId":"listReservationInvoices","parameters":[{"$ref":"#/components/parameters/ReservationUUID"}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Invoice"},"type":"array"}}},"description":"Invoices. The array is the response body itself (existing envelope)."},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"carsanKeyBearer":[]},{"carsanKeyHeader":[]}],"summary":"All invoices of an own trip","tags":["reservations"],"x-carsan-availability":"planned","x-carsan-key-capability":"read_only","x-carsan-key-enabled":true,"x-carsan-phase":2}},"/my/reservation/{uuid}/payment-link":{"post":{"description":"Returns a Carsan trip URL (`/trips/{uuid}?intent=pay\u0026payment_type=reservation|deposit`). No\npayment is created or executed and no provider is called. Amounts are fetched on the page,\nnever from the link. `payment_type` takes the charge values `rent` or `deposit`; the page\nparameter spells rent as `reservation`.\nRefusals: `nothing_to_pay` (409) — no unpaid invoice of that type for this customer;\n`reservation_cancelled` (409); `invalid_payment_type` (400).\n","operationId":"getPaymentLink","parameters":[{"$ref":"#/components/parameters/ReservationUUID"},{"$ref":"#/components/parameters/AgentClient"}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"payment_type":{"enum":["rent","deposit"],"type":"string"}},"required":["payment_type"],"type":"object"}}},"required":true},"responses":{"200":{"$ref":"#/components/responses/ManualAction"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"`invalid_payment_type`, `invalid_request_body` or `invalid_reservation_id`."},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The action is not available for this reservation now (see `error_code`)."},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/Unavailable"}},"security":[{"carsanKeyBearer":[]},{"carsanKeyHeader":[]}],"summary":"Link for the customer to pay rent or deposit","tags":["manual-actions"],"x-carsan-availability":"planned","x-carsan-key-capability":"read_only","x-carsan-key-enabled":true,"x-carsan-phase":2}},"/my/trips":{"get":{"description":"Upcoming/active and historical trips, including completed and cancelled ones, each with a `financial_summary`.","operationId":"listTrips","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"properties":{"active":{"items":{"$ref":"#/components/schemas/Trip"},"type":"array"},"history":{"items":{"$ref":"#/components/schemas/Trip"},"type":"array"}},"required":["active","history"],"type":"object"}},"required":["data"],"type":"object"}}},"description":"Trips grouped as `active` and `history`."},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"carsanKeyBearer":[]},{"carsanKeyHeader":[]}],"summary":"Own trips","tags":["reservations"],"x-carsan-availability":"planned","x-carsan-key-capability":"read_only","x-carsan-key-enabled":true,"x-carsan-phase":2}},"/my/verification":{"get":{"description":"Compact status only. Reading it never starts, restarts or submits verification and makes no\nprovider request. The customer starts and completes KYC personally in the Carsan app. A\nmanager's decision is never disclosed.\n","operationId":"getVerification","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/VerificationStatus"}},"required":["data"],"type":"object"}}},"description":"Verification status."},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"security":[{"carsanKeyBearer":[]},{"carsanKeyHeader":[]}],"summary":"Own verification status (read-only)","tags":["account"],"x-carsan-availability":"planned","x-carsan-key-capability":"read_only","x-carsan-key-enabled":true,"x-carsan-phase":2}},"/reservation/quote":{"post":{"description":"Computes the current price. Writes nothing and holds nothing. Anonymous calls are allowed;\npersonal promo eligibility is then unknown and is checked again at creation.\nUnset options default to `minimum` protection, `limited` mileage and `pickup`.\n`final_total` excludes the deposit; the deposit is `deposit_cents`.\nA customer key is optional. With a valid key, personal promo eligibility is checked and the\ncall uses the key's own rate budget. An invalid, revoked or conflicting credential is\nrejected with 401; it never falls back to an anonymous quote.\n","operationId":"quoteReservation","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Quote"}},"required":["data"],"type":"object"}}},"description":"The quote. All amounts are integer USD cents."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid input: dates outside operating hours or in the past, unknown protection plan, or\na promo error (`promo_codes_disabled`, `promo_code_not_found`, `promo_code_invalid`,\n`promo_already_used`).\n"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No such car."},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/Unavailable"}},"security":[{},{"carsanKeyBearer":[]},{"carsanKeyHeader":[]}],"summary":"Price quote for dates and options","tags":["cars"],"x-carsan-availability":"available","x-carsan-key-capability":"read_only","x-carsan-key-enabled":true,"x-carsan-phase":1}}},"security":[],"servers":[{"description":"Production","url":"https://api.carsan.com/v1"}],"tags":[{"description":"Car search, detail, availability and quotes. No account needed.","name":"cars"},{"description":"The customer's own profile, verification status and saved card.","name":"account"},{"description":"The customer's own trips and invoices; create and cancel are planned for keys.","name":"reservations"},{"description":"Links the customer opens to pay, add a card or extend. The API executes none of these.","name":"manual-actions"}]}