
Talking to someone else's API without writing HTTP glue again
2 Jul 2026
Every integration with an external API starts the same way: read the docs, figure out auth, write a thin wrapper around HTTP(), add retry logic nobody asked for until the third outage, and repeat for the next vendor. Phlo's connectors framework exists to stop repeating that part.
One base class, one contract
Every connector extends a shared Connector base: credential resolution from a creds.ini section, JSON request helpers built on HTTP(), opt-in idempotent retry, pagination, and a normalized result shape, obj(ok, status, data, error), so calling code never branches on a vendor-specific response format.
$res = (new Shopify)->orders(['status' => 'open'])
if (!$res->ok) return error($res->error, $res->status)
foreach ($res->data AS $order) ...
OAuth-based providers share a further OAuthConnector base with a TokenStore that refreshes automatically, so token expiry is handled once, in the shared base class, not once per integration.
What ships today
Shopify and Lightspeed for retail, Slack, Telegram, Twilio and MessageBird for messaging, Resend for transactional mail, Moneybird, Exact Online and e-Boekhouden.nl for accounting, Microsoft Graph, Google Calendar and Google Sheets for the Google and Microsoft ecosystem. Each one is a thin, documented class on top of the same contract, not a bespoke SDK with its own idioms to relearn.
QUERY, for reads with a body
A more recent addition to the connector contract is the QUERY HTTP method (RFC 10008): a safe, idempotent read that carries a request body, for a lookup whose filters do not fit cleanly in a URL. route QUERY search => $this->search parses like any other route, %payload decodes the QUERY body the same way it decodes a POST, and HTTP() takes a matching QUERY: argument, so a connector or your own app can call an API that expects exactly this shape without hand-rolling it.
The part that actually saves time
The value is not any single connector, it is that adding the next one means implementing the vendor-specific request shape once and inheriting credential handling, retry and pagination for free. An integration that would otherwise be a small bespoke project becomes an afternoon of mapping one API's endpoints onto a contract that already works.