Documentation

Integrations overview

How AppEngine talks to external vendors — Upstream for API calls, Connect for OAuth and webhooks.

External services — Stripe, Twilio, Facebook, Google, every email vendor — live behind a single abstraction in AppEngine. Two modules cooperate. Upstream is the runtime call layer: a unified shape for "make a call to vendor X, operation Y". Connect handles OAuth flows and inbound webhooks. Most code touches Upstream; Connect runs mostly on its own once you've configured a vendor.

Upstream

The Upstream module abstracts vendor APIs so application code calls them by use-case rather than by SDK. A "send email" call is the same shape whether the configured vendor is SendGrid, Mailgun, or AWS SES.

POST/upstream/call/:integration/:operationJWT
GET/upstream/call/:integration/:operationJWT
POST/upstream/test/:integration/:operationJWT
POST/upstream/save-integrationJWT
GET/upstream/integration-types/:type?JWT
GET/upstream/active/:type?JWT
POST/upstream/shutdown/:idJWT

integration-types returns the catalogue of supported vendors per category (payment, email, sms, social, ads, shipping, ai). active returns the org's currently-configured integrations. call invokes an operation against the configured vendor — the SDK selection happens server-side based on the integration type.

// Send an SMS without caring whether the vendor is Twilio or Vonage
await fetch('/api/upstream/call/sms-provider/send', {
  method: 'POST',
  headers: { orgid: ORG_ID, Authorization: `Bearer ${jwt}` },
  body: JSON.stringify({
    to: '+15551234567',
    body: 'Your verification code is 123456',
  }),
});

The use-case routing endpoint POST /upstream/service/:serviceName/:operation picks a vendor based on the org's preferred provider for the service — useful when multiple vendors are configured.

Connect

The Connect module is the OAuth and webhook handler. It owns three URL families:

GET/connect/oauth2callback/:vendorNo auth
POST/connect/webhook/:vendor/:serviceId?No auth
GET/connect/webhook/:vendor/:serviceId?No auth
POST/connect/automation/:id/:stepId/:entity/:activity/No auth
GET/connect/automation/:id/:stepId/:entity/:activity/No auth

oauth2callback is where every vendor sends the user back after consent. The vendor segment routes to the correct token-exchange handler (Stripe, Facebook, Google, etc.). webhook is the inbound endpoint vendors POST events to — Stripe payment events, Facebook page events, Twilio call status. automation/... is the unified tracking endpoint for emails, links, forms, and pages — pixels and click-redirects route through here.

Vendor catalogue

Connectors implemented today:

CategoryVendors
PaymentStripe, PayPal, Helcim
SMS / VoiceTwilio
EmailSendGrid, Mailgun, AWS SES
SocialFacebook, TikTok, LinkedIn, Twitter, Pinterest
OAuth / cloudGoogle (Gmail + Ads), GitHub
ShippingEasyPost
DesignFigma

Per-vendor guides cover the OAuth flow, supported operations, webhook events, and known quirks. See the vendor guides index.

Auth and tenancy

Every integration is scoped to an org. The same vendor can be connected by multiple orgs, each with its own credentials. Connect tokens are encrypted at rest. The orgid header drives credential lookup on every Upstream call — there is no "global" Stripe key.

Configuration storage

GET/upstream/get-config/:type?/:configId?JWT
POST/upstream/get-integrationJWT
POST/upstream/save-integrationJWT

Integration config records live in the data layer (integration collection) but you should always go through the Upstream service so encryption and validation run. The service handles secret rotation, partial updates (don't overwrite the whole credential blob), and connection testing before save.

What this module is not

  • It is not a webhook subscription manager for application-level events. For "notify my URL when a customer is created" you want the Webhooks interface (TBD — currently use the Automation "send webhook" action).
  • It is not the AI provider abstraction. AI vendors (OpenAI, Anthropic, Gemini) plug in via the Usage module keys, not Connect.

Next steps