Muse courier connector
Autolane’s courier connector lets an AI agent hand a curbside food order to an Autolane vehicle. The agent places the order on the store’s website in the user’s own name. An Autolane vehicle collects it at the curb and drives it to the user’s address. Muse, Meta’s agent, is the first client.
This page is the full reference for agent developers and reviewers: who can use the connector, how clients authenticate, the six tools, every response and error, payment, limits, and how Autolane handles data.
At a glance
Access requirements
People
During the pilot, access is by invitation: Autolane enables each mobile number. A number that is not enabled sees this message at the phone step, and no code is sent:
Autolane Courier isn’t available for this number yet.
If Autolane removes a number later, it loses access at its next MCP call (401) or token refresh (invalid_grant), whichever comes first.
Each person needs:
- A mobile number that receives SMS, entered with its country code. A 10-digit number typed without
+is read as a US number (+1is added). - A store and a drop-off address inside the same Autolane service area in Austin.
- To accept the delivery terms and the text-message consent that the agent shows before it reserves a vehicle.
Clients
An agent client must support:
- MCP over Streamable HTTP.
- The OAuth 2.1 authorization code flow with PKCE
S256, sending the RFC 8707resourceparameter. - Discovery through RFC 9728 (protected resource metadata) and RFC 8414 (authorization server metadata).
- RFC 7591 dynamic client registration with a redirect URI that Autolane has allowlisted. To add a redirect URI, email support@goautolane.com.
- Showing the user the price, the terms and the consent text before the reserve.
- Taking payment for the delivery fee through the hosted Stripe Checkout link or a Stripe shared payment token.
- Placing the store order on the store’s website in the user’s own name.
What Autolane serves
- Stores. Restaurants and other prepared-food businesses with curbside pickup: restaurants, cafes, bakeries and takeout. The store must appear on Google Maps at the address given, with a phone number and opening hours, and the agent must list curbside among the store’s pickup options.
- Stores Autolane refuses, whatever the cart holds: liquor stores, pharmacies and drugstores, convenience stores, gas stations, supermarkets, grocery and food stores, markets, warehouse, discount and general stores, wholesalers, bars, pubs, breweries, wineries and night clubs, casinos, smoke shops, and entertainment venues such as karaoke bars, comedy clubs, dance halls, live music venues, bowling alleys and cinemas.
- Check-in. The vehicle cannot use a store’s own app. A store whose only check-in is its app is declined (
app_only_check_in). - Timing. Autolane offers 15-minute pickup windows from the store’s lead time up to 90 minutes ahead, inside both the store’s opening hours and Autolane’s service hours (8 AM to 8 PM, store time). It does not take orders for later than that.
- Restricted items. Never use Autolane for alcohol, tobacco, vape and nicotine products, pharmacy and prescription items, lottery, firearms and ammunition, or any order that needs an ID or an age check at pickup. Autolane screens the items on every order and will not deliver them.
- Pickup requirements. An order is not serviceable when pickup needs an ID, a name match with the person collecting, a signature or an age check (
id_required,name_must_match,signature,age_restricted). Autolane never provides a pickup person’s name or a license plate. If checkout requires either and accepts nothing else, the order is not serviceable.
Authentication
Autolane’s authorization server is the MCP resource itself. Its issuer is https://mcp.goautolane.com/api/delivery-mcp, and every OAuth endpoint sits under that path. While Autolane has the connector paused, the MCP endpoint, the four OAuth endpoints and the authorization server metadata answer 404.
Step 1: get the 401
Call the MCP endpoint with no token. The WWW-Authenticate header points to the protected resource metadata.
Step 2: read the protected resource metadata (RFC 9728)
The response carries Cache-Control: max-age=3600 and allows any origin.
Step 3: read the authorization server metadata (RFC 8414)
The issuer has a path, so under RFC 8414 section 3.1 the metadata is served only at /.well-known/oauth-authorization-server/api/delivery-mcp. The root /.well-known/oauth-authorization-server has nothing for this server.
The response carries Cache-Control: public, max-age=300 and allows any origin.
Step 4: register the client (RFC 7591)
Other fields are ignored. Every redirect URI must be an absolute https URL with no fragment and must match an entry on Autolane’s allowlist exactly, character for character. To add a redirect URI, email support@goautolane.com.
Autolane issues no client secret. Errors:
Step 5: send the user to authorize
Open the authorization endpoint in the user’s browser.
What the user sees.
- Phone page. Titled “Link your phone”, with the heading “Link your phone to” and the client’s
client_name, and the line “Autolane texts a code to the number that will get delivery updates.” The user enters a mobile number and taps Text me a code. Spaces, dots, dashes and parentheses are ignored. A number typed without+is read as follows: 10 digits gain+1(a US number); any other length gains+and is read as starting with its country code. The result must be in E.164 form (+and 7 to 15 digits). - Code page. Titled “Enter your code”: “We texted a 6-digit code to the number ending” and the last four digits. The user enters the code and taps Link phone.
- Redirect. Autolane links the number and redirects the browser to your
redirect_uriwithcodeandstate.
The request is good for 10 minutes from the first page load. The authorization code is good for 60 seconds and works once.
Errors shown on the page, never redirected. These come before Autolane trusts the redirect URI (OAuth 2.1 section 4.1.2.1), or after the user has started the phone step.
Errors redirected to the client. Once the client and redirect URI pass, faults go back to redirect_uri with error, error_description and state (when you sent one).
Messages at the phone and code steps. These show on the page, and the user can try again.
Step 6: exchange the code for tokens
The token endpoint takes application/x-www-form-urlencoded only. Send client_id in the body; there is no client secret.
(Line breaks added for reading; send one line.) code, redirect_uri and code_verifier are required. redirect_uri must equal the one used at authorize. code_verifier is 43 to 128 characters from A-Z a-z 0-9 - . _ ~. resource is optional here; when sent it must equal the resource of the authorization request.
Tokens are opaque strings. Every error has the body {"error": "...", "error_description": "..."}:
Step 7: refresh
The response has the same shape as step 6. Refresh tokens rotate: each refresh revokes the token you sent and returns a new access token and a new refresh token. Store the new refresh token and drop the old one. If a refresh token is used a second time, Autolane revokes every token in its family, and the user must link again.
The refresh also checks that Autolane still enables the user. If not, it answers 400 invalid_grant with This user is not enabled for Autolane Courier, and issues no tokens. Drop the refresh token. A new authorization attempt stops at the phone step.
Step 8: revoke (RFC 7009)
Revoking a refresh token revokes its whole family, including live access tokens. Revoking an access token revokes only that token. The answer is 200 with an empty body even when the token is unknown or belongs to another client. token and client_id are required (400 invalid_request, token and client_id are required). The rate limit is the token endpoint’s (429, Too many requests; wait and retry).
Step 9: call the MCP endpoint
Send the access token as a bearer token on every request.
The endpoint answers 401 with the header and body from step 1 when:
- the request has no
Authorization: Bearerheader; - the token is unknown, expired or revoked, is a refresh token, or was issued for another resource;
- Autolane no longer enables the user’s number.
On a 401, refresh once. If the refresh fails with invalid_grant, run authorization again. An access token belongs to one user: every delivery it creates or reads is scoped to that user, and another user’s delivery_id reads as not_found.
Token lifetimes
Call flow
One delivery_id covers a delivery from the first check to the end. Follow this order:
- Check. Call
check_deliverybefore checkout starts, with the store, the drop-off address, the store’s pickup options, the timing and any store pickup slots. It answers serviceable or a decline, with the price,pickup_windows(best first), the terms, the consent text andquote_expires_at. After a decline, do not place the store order for Autolane delivery. - Show. Show the user the price, the terms text and the consent text.
- Reserve. At checkout, call
reserve_deliverywith the customer’s name, consent and terms acceptance. Omitcontact.phoneor send the number the user linked. It holds a vehicle for 15 minutes and returnspickup_profile(what to enter at checkout),pickup_time.select,hold_expires_atand thepaymentrequest. - Pay. Get the user’s approval for the fee and send the payment credential before you submit the store order. See Payment.
- Order. Submit the store order in the user’s name, then call
confirm_deliveryright away with the order number, the items and the confirmation text (and the pickup code when the store shows one). It returnsplanned_pickup_time,estimated_delivery_windowandtracking_url. - Track. Poll
get_delivery_statusand follownext_step. The user can follow the delivery throughtracking_url.
Use update_delivery for anything that changes after the reserve. If the user abandons the order or picks another store after a reserve, call cancel_delivery so the vehicle is released.
Clocks
If the hold ran out before you submitted the store order, call reserve_delivery again first. If you submitted the order without a live hold, confirm_delivery takes a new hold itself; when no vehicle is free it declines the delivery with no_capacity instead of booking it.
Tools
The server also offers one resource, courier://description (title “Autolane courier connector”, text/markdown). It holds the connector’s instructions to the agent: the call order, the restricted goods, the payment rules and the check-in rules.
Rules every tool shares
Idempotency. Every tool except get_delivery_status takes an idempotency_key: 8 to 128 characters, with no NUL byte. Keys are scoped to the linked user and kept for 48 hours.
- When you retry a call, send the same key and the same arguments.
- A stored success or decline replays: a retry returns the first answer again (with a fresh
tracking_urlwhere one applies). - The same key with different arguments answers
idempotency_conflict. - A refusal (an envelope with an
error) is never stored, so a retry with the same key runs the call again. - A retry that arrives while the first call is still running waits up to 10 seconds, then answers
internal_errorwithA call with this idempotency_key is still in flight. Retry again with the same key.
Address object (store_address, dropoff_address):
Other shared types:
Result shape. Every call the MCP layer accepts returns a CallToolResult with:
structuredContent: the response envelope (see Responses);content: onetextitem holding the same envelope as JSON;isError: trueonly when the envelope’serror.codeisinternal_error.
Other refusals, such as rate_limited, invalid_state or not_found, are ordinary results with an error object in the envelope. Arguments that fail a tool’s input schema (a missing field, a wrong type, a string too long) never reach Autolane’s code: the MCP layer refuses them with its own validation error naming the field, with no envelope, next_step or user_message. Fix the field and retry.
Every envelope has next_step (the exact call to make next) and user_message (one sentence you may show the user). Follow next_step.
check_delivery
Asks whether Autolane can deliver a curbside order from this store to this address. Call it before checkout starts. It creates the delivery and returns its delivery_id.
Response. A serviceable check returns state: "quoted" and these fields:
The check carries no payment_status or fee_cents; those appear after the reserve.
Declines. state: "declined", serviceable: false and a decline_reason: no_curbside, store_not_supported, disqualifying_requirement, out_of_zone, outside_service_hours, no_capacity or timing_not_feasible. next_step is “Tell the user Autolane cannot deliver this order; do not place the retailer order for Autolane delivery”. A decline is stored, so a retry with the same key returns it again.
Errors. rate_limited; idempotency_conflict; internal_error, including Store lookup is unavailable; retry with the same idempotency_key and Address lookup is unavailable; retry with the same idempotency_key.
reserve_delivery
Holds an Autolane vehicle for 15 minutes at checkout. Returns what to enter at checkout and the payment request.
Response. state: "held" with:
pickup_time depends on the store:
- Stores where the kitchen starts when the vehicle checks in:
selectisasap, with “Place the order now; the vehicle checks in on arrival and the kitchen starts then”. - Stores with pickup slots, when a slot fits:
selectis the slot’s label, id, or start and end, with “Select the retailer pickup slot” and the slot name, then “at checkout”. - Stores with pickup slots, when none was chosen:
selectis a time, with “Select the earliest retailer pickup slot at or after” that time.
Keep the order in the user’s own name and use the customer’s own email. Calling reserve_delivery again on the same delivery while the hold is live keeps that hold and its end time; after the hold lapses, it takes a new 15-minute hold. A reserve for a different store releases the user’s earlier hold that has no store order yet; its id appears in released_delivery_ids and user_message adds “An earlier Autolane hold was released.”
Declines. The delivery becomes declined and the hold is released: store_not_supported, disqualifying_requirement, app_only_check_in, customer_unreachable (the number has opted out of texts) or no_capacity. next_step is “Do not submit the retailer order for Autolane delivery; tell the user why”.
Errors.
confirm_delivery
Tells Autolane the store order is placed, and books the delivery. Call it right after you submit the store order.
Response. state: "booked" with:
A confirm on a delivery that is already booked returns the booking again.
Declines. The store order already exists, so next_step is “Tell the user the order is ready for regular curbside pickup at the store; Autolane cannot deliver it”. Reasons: customer_unreachable (no reserve ran), store_not_supported, timing_not_feasible, no_capacity and disqualifying_requirement (a restricted item).
Errors.
update_delivery
Reports payment, or a change after the reserve. Send delivery_id, update_type, details and idempotency_key. Autolane checks details against the schema for the type; a mismatch answers invalid_input with details for and the type, then the first problem found.
States in this table are stored states: booked covers what get_delivery_status shows as booked, picked_up, delivered and failed.
The method and check_in_method values are email_link, order_page, call_store, unknown and app_only.
Response. The common envelope (delivery_id, state, next_step, user_message, retailer_name, store_address, retailer_order_number when known, payment_status, fee_cents) with nothing type-specific. user_message by type:
Declines. Only requirement_found while held declines, with disqualifying_requirement or app_only_check_in.
Errors. invalid_input; not_found; hold_expired (any type but payment, when the hold lapsed and no store order was submitted); invalid_state (including The order is already collected); timing_not_feasible; payment_failed; internal_error (including The payment provider did not answer); idempotency_conflict; rate_limited.
get_delivery_status
Reads the delivery’s state. Send only delivery_id; there is no idempotency key.
Response.
Errors. not_found, rate_limited, internal_error.
cancel_delivery
Cancels the delivery. Allowed until the vehicle has collected the order. Not needed after update_delivery with order_failed.
Response. state: "cancelled", payment_status, fee_cents and fee_charged. next_step is “Tell the user the delivery is cancelled”. user_message is “Your Autolane delivery is cancelled and no fee was charged.” (or “Your Autolane delivery is cancelled and the delivery fee was charged.” when fee_charged is true). A cancel before the vehicle collects the order releases the fee authorization.
Errors. not_found; invalid_state (The order is already collected, or Not allowed while and the state on a declined or cancelled delivery); idempotency_conflict; rate_limited; internal_error.
Responses
Envelope
Every accepted call returns this object as structuredContent and as JSON text.
A refusal repeats the delivery’s delivery_id, state, payment_status, retailer_name, store_address, retailer_order_number and fee_cents when the tool had loaded them.
Error codes
Each code has a fixed user_message:
Decline reasons
A decline is not an error. The call succeeds with state: "declined" and a decline_reason, and a retry with the same key returns it again.
When a store order was already submitted, disqualifying_requirement and no_capacity add ” Your order is ready for regular curbside pickup at the store.”
Delivery states
status_detail
When sms_reachable is false, the messages from scheduled through en_route_to_customer add ” Autolane cannot text this phone; share the tracking link.” The arrived_at_customer message does not change and still points to the texted link, which the customer did not get. In that case, do not repeat it: tell the user the vehicle is outside and Autolane’s dispatch will call them to hand over the order. When the customer replies STOP, Autolane alerts dispatch to call them before the vehicle arrives.
When the vehicle reaches the store, do not check in on the store’s order page, email link or confirmation text yourself. Autolane’s supervisor checks the order in with the store by phone. Call update_delivery with checked_in only if the user tells you they already checked the order in themselves.
Polling
next_step on every status read says when to poll again:
Each delivery gets one fresh read every 120 seconds, or every 30 seconds from the time the vehicle leaves for the store until it leaves the store with the order. A read inside that allowance is not refused: it returns the last stored result with cached: true and a fresh tracking_url.
Payment
The fee. Autolane charges a delivery fee, $4.95 today. Every check quotes it (price.amount, in dollars), and every response after the reserve carries it as fee_cents. Autolane charges the fee itself, separately from the store order; the user pays the store for the food as usual.
The payment request. In production, reserve_delivery returns a payment block:
Get the user’s approval for the fee, then pay one of two ways, before you submit the store order:
- Hosted Checkout. Send the user to
checkout_url. When they finish, callupdate_deliverywithupdate_type: "payment"anddetails: { "checkout_completed": true }. Autolane checks the session and answerspayment_status: "authorized", orpayment_failed. - Shared payment token. Get a Stripe shared payment token scoped to
seller_profile_idand send it withupdate_delivery(update_type: "payment",details: { "shared_payment_token": "..." }), or onreserve_deliveryorconfirm_deliveryaspayment.shared_payment_token.
When a payment is already authorized, the payment block has no checkout_url and instruction says no further payment step is needed.
Authorize, then capture. Autolane authorizes the fee when you send the credential and captures it after the order is delivered. If the delivery ends any other way (cancelled, declined, or not completed), Autolane releases the authorization and charges nothing. The terms let Autolane keep the fee when the store cannot hand over the order, the order holds items Autolane cannot carry, or the user cancels after the vehicle collects it; Autolane does not charge it in those cases today.
Declines. A declined payment answers payment_failed. Get a new credential and send it the same way; each new credential starts a new attempt. Resending the same token returns the same attempt. A token already used on another delivery is refused. If the hold has lapsed, call reserve_delivery again first, then send the credential.
Store order submitted without a payment. Never submit the store order before the fee is authorized. If it happens, Autolane still books the delivery from the recorded order. Status then shows payment_status: "unpaid" (or "failed" after a decline), and next_step asks for a credential. A booked delivery still accepts one, before or after delivery.
Limits
Tool rate limits. A call over a limit answers rate_limited (“Wait and retry”).
OAuth rate limits. Over a limit, the endpoint answers 429 with no Retry-After header.
OAuth body sizes. Form bodies (authorize, token, revoke) up to 16,384 bytes. JSON bodies (register) up to 65,536 bytes.
Main input bounds.
Data and privacy
What Autolane receives. From the agent: the store’s name, address and website; the drop-off address and notes; the requested timing, the store’s pickup options and slots; the customer’s first and last name, the linked mobile number and an optional email; the consent and terms acceptance, with versions and time; pickup requirements and notes; the check-in method, link and instructions; the store order number, name on the order, items (names, quantities, modifiers), subtotal, confirmation text, ready time, store messages and pickup code; and any cancel reason. From sign-in: the mobile number and when it was last verified. Autolane stores authorization codes and tokens only as hashes.
Third parties.
Autolane never receives card numbers. Card details go to Stripe through Checkout or the shared payment token.
Retention. The store’s confirmation text and store messages are deleted 90 days after the delivery closes. Autolane keeps the delivery record, including the consent record, for support, billing and compliance.
Texts the customer receives
Autolane texts the linked mobile number. The links below point to the customer’s own tracking page.
Booking. Sent once, right after the delivery is booked, unless the number has opted out:
On the way. Texts when the vehicle sets off for the store, when it leaves the store with the order, and when it is almost at the drop-off.
Arrival. The arrival text carries the link that opens the trunk:
If the vehicle is still waiting near the end of that time, a last-call text follows before it leaves.
Cancelled after booking. When Autolane cannot deliver but the store order stands:
When the store order did not go through:
A cancel the user asked for sends no text.
STOP, START and HELP.
- Reply STOP to stop the texts. Autolane’s dispatch then calls the customer about any delivery in progress. STOP does not cancel the order. After STOP,
sms_reachablereadsfalse; sharetracking_urlwith the user. - Reply START to resume the texts.
- Reply HELP for help.
The agent’s tracking link. The tracking_url that the tools return is status-only: it shows the delivery’s state, times and vehicle description, with no license plate, no location and no trunk control. It lasts 24 hours, and every status read returns a fresh one. The trunk opens only from the link Autolane texts the customer; for a customer who replied STOP, dispatch calls instead.
Support
Email support@goautolane.com with the delivery_id or the tracking link.