Developer Connectors
Connect your own service to Drivehelp so the voice co-pilot can use it while someone drives: "Order my usual from my McDonald's connector", "Open the garage", "Log this delivery".
- The driver adds a connector in Settings → For developers → Connectors. They enter a name, a sentence telling the co-pilot what the connector does, an HTTPS URL, and a token.
- The co-pilot (Claude, using the driver's Drivehelp credits) decides when to call the connector, and relays its replies by voice.
- Calls go straight from the iPhone to your server. They never pass through Drivehelp's servers.
There are two kinds of connector.
| Kind | Use it when | The co-pilot calls |
|---|---|---|
| Conversation (recommended) | Your service should talk back: ask questions, confirm an order | POST <your URL> with each message |
| REST API | You already have a JSON API | GET/POST/PUT/PATCH/DELETE <your URL><path> (the driver picks which methods are allowed) |
Conversation protocol: drivehelp.connector/1
Drivehelp sends one POST per message to the exact URL the driver entered.
POST https://api.example.com/drivehelp
Authorization: Bearer <driver's token> (or <Header-Name>: <token>, or nothing)
Content-Type: application/json
Accept: application/json
User-Agent: Drivehelp-Connector/1
X-Drivehelp-Protocol: 1
{
"protocol": "drivehelp.connector/1",
"conversation_id": null,
"message": "I'd like to order lunch",
"context": {
"app": "Drivehelp",
"locale": "en_US",
"time": "2026-10-12T17:04:05Z",
"time_zone": "America/Chicago",
"location": { "lat": 32.8141, "lon": -96.9489 }
}
}
conversation_idisnullon the first message. After that, Drivehelp sends back whatever you returned.locationis included only if the driver turned on Share my location with it for your connector. It is rounded to about 10 m.- The Test connection button sends
"message": "ping".
Your reply
{
"reply": "Sure! What would you like? Your usual is a McChicken meal.",
"conversation_id": "c_81f2",
"done": false
}
| Field | Meaning |
|---|---|
reply | What you want the driver to hear. Keep it short; it's read aloud. |
conversation_id | Your session id. Drivehelp sends it back with the next message. |
done | true when the conversation is finished. |
needs_confirmation | Optional: {"summary": "Place order: McChicken meal, $8.49, pickup at Belt Line Rd"}. Use this before anything that costs money or can't be undone. |
Confirmations: the driver approves, not the AI
When your reply includes needs_confirmation, Drivehelp asks the driver itself. It shows an Allow/Deny card and asks aloud "Should I go ahead? Say yes or no". It then sends the answer straight back to you:
{ "protocol": "drivehelp.connector/1", "conversation_id": "c_81f2", "message": "confirmed", "confirm": true, ... }
The declined form is "message": "declined", "confirm": false.
Only act when confirm is true. The co-pilot cannot produce that value, because the app sets it only from the driver's tap or spoken "yes". If nobody answers within 45 seconds, it counts as declined.
Example: a whole order
| From | Message |
|---|---|
| Driver | "Order lunch from my McDonald's connector." |
| Drivehelp → you | {"message": "Order lunch", "conversation_id": null} |
| You → | {"reply": "Your usual McChicken meal, or something else?", "conversation_id": "c1", "done": false} |
| Co-pilot → driver | "McDonald's asks: your usual McChicken meal, or something else?" |
| Driver | "The usual, large fries." |
| Drivehelp → you | {"message": "The usual, large fries", "conversation_id": "c1"} |
| You → | {"reply": "Got it.", "conversation_id": "c1", "needs_confirmation": {"summary": "McChicken meal, large fries, $9.29, pickup at Belt Line Rd"}} |
| Drivehelp → driver | On screen, and aloud: "McDonald's: McChicken meal, large fries, $9.29… Should I go ahead?" The driver says "Yes." |
| Drivehelp → you | {"message": "confirmed", "confirm": true, "conversation_id": "c1"} |
| You → | {"reply": "Order placed! Ready in 6 minutes.", "done": true} |
Minimal PHP endpoint
<?php
declare(strict_types=1);
header('Content-Type: application/json');
$expected = 'replace-with-a-long-random-token';
$auth = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
if (!hash_equals('Bearer ' . $expected, $auth)) { http_response_code(401); echo '{"error":"unauthorized"}'; exit; }
$in = json_decode(file_get_contents('php://input') ?: '', true);
if (!is_array($in) || ($in['protocol'] ?? '') !== 'drivehelp.connector/1') { http_response_code(400); echo '{"error":"bad_request"}'; exit; }
$id = $in['conversation_id'] ?? bin2hex(random_bytes(8));
$message = trim((string)($in['message'] ?? ''));
if ($message === 'ping') { echo json_encode(['reply' => 'pong', 'conversation_id' => $id, 'done' => true]); exit; }
if (($in['confirm'] ?? null) === true) {
// The driver said yes in the app: do the real thing here.
echo json_encode(['reply' => 'Done! Order placed.', 'conversation_id' => $id, 'done' => true]); exit;
}
if (($in['confirm'] ?? null) === false) {
echo json_encode(['reply' => 'Okay, cancelled.', 'conversation_id' => $id, 'done' => true]); exit;
}
echo json_encode([
'reply' => "Got it: \"$message\".",
'conversation_id' => $id,
'needs_confirmation' => ['summary' => "Place order: $message"],
]);
REST connectors
The co-pilot can call method + path (+ query + JSON body) under the base URL. Example: base https://api.example.com/v1 plus path /orders gives https://api.example.com/v1/orders.
The driver chooses which methods are allowed. With the default setting Ask me: Before changes, every POST/PUT/PATCH/DELETE waits for the driver's own Allow (on screen, or by voice). The other settings are Before every call and Only when the endpoint asks.
Security model (what Drivehelp guarantees)
Connectors are a way for outside code and outside text to reach the co-pilot, so they are treated as untrusted at every step.
Where calls can go
- HTTPS only, on ports 443 or 8443. No usernames or passwords in the URL.
- Public hosts only.
- IP-address hosts are refused, including decimal and hex forms.
- Names that resolve to loopback, private LAN, link-local or cloud-metadata (169.254.x), carrier-grade NAT, or multicast addresses are refused. This is checked just before every call.
.local,.internal,.lan,.home.arpaand similar names are refused.
- Never Drivehelp's own servers:
bigmesoftwares.comand every subdomain is blocked. Connector traffic also never goes through Drivehelp's servers, so a connector is not a door into them. The app's community key and device ID are never attached to connector calls. - Never AI providers (
anthropic.com,claude.ai,openai.com). Connector calls can't be pointed at them. - The co-pilot cannot choose where a call goes.
- It can't pick the host, headers or token, only a path, query and body.
- Paths must start with
/, and may not contain..,//,\,@,#,?, encoded dots or slashes, spaces or non-ASCII characters. - The final URL must have the same host, port and base path as the URL the driver entered.
- No redirects are followed. No cookies, cache or shared credentials are used (an ephemeral session).
Tokens
- Tokens live in the iOS Keychain on this device only.
- The co-pilot never sees them, and they are redacted from replies if an endpoint echoes them back.
Limits
- Requests: 8 KB maximum, 15-second timeout.
- Responses: the first 64 KB are read, and the co-pilot sees at most 6,000 characters.
- At most one call every 1.5 seconds and 30 calls an hour per connector, and 4 connector calls per request.
Protection against prompt injection
- Everything a connector returns reaches the co-pilot inside
<connector_response untrusted="true">, labeled as third-party data. Any copy of that tag inside a reply is defused. - Once a connector has answered, the rest of that request cannot:
- call a different connector;
- remember or forget things, or change home, routines, places, cars, speed limit, route preferences, fuel or service logs;
- post to other drivers;
- control the app.
- Anything that changes something is approved by the driver in the app, outside the AI, by tap or voice. A connector or a confused model can't approve itself.
Visibility
- Settings → Connectors shows recent activity: method, path, status and time. Bodies and tokens are never logged.
- Connectors can be turned off or deleted at any time, and deleting one also deletes its token.
What you should do on your side
- Use a long random token and check it with a constant-time compare (
hash_equalsin PHP). - Act on purchases only when
confirm: true. Treatmessageas untrusted user text. - Rate-limit by token. Return short replies, and use
done: truewhen the conversation is finished.
Connectors are optional. The co-pilot's part uses the driver's Drivehelp credits; the connector call itself goes straight from the phone to your endpoint. The service behind a connector, and anything it charges or orders, is the responsibility of whoever runs it and the driver who adds it (see our Terms and Privacy Policy). Questions? Email abovealltheselove@gmail.com or call +1 (469) 345-1412.