External services
Call an outside API does the whole job, start to finish.
An external service is another company's API, such as Stripe, a courier
or another Jadpo app, that your actions call. You call it like an SDK:
couriers.bookings.create(request). Jadpo makes the HTTP request, adds the
secret, picks the host, retries and reads the response. Your code never
builds a URL, sets a header or sees a raw response.
What a typical app needs
Take a shop. This is what it needs from outside its own code, and what you write for each:
| It needs | You write |
|---|---|
| A database | One connection in app.jadpo, to PostgreSQL |
| To send email | A connection to a mail server or a mail service such as Resend, and a type for each email |
| To keep uploaded files | A connection to one server's disk, and a File field. Storing files in S3 isn't built yet |
| To call a company's API, such as a courier's | A provider package, which describes that API; a connection to it; a call in an action |
| To hear back from that company | A webhook secret on that connection, and a subscriber |
| To share pure helpers between apps, such as a postcode parser | A library package, which needs no connection |
| Feature flags, an audit trail, search | Nothing from outside: they are built in, and keep their data in your database |
None of this uses Docker or Podman. Running a service such as Gotenberg in a container beside your app is planned and isn't built yet: Running a service in a container.
A provider package is Jadpo source that lists an API's operations, types,
failures and webhook events. It also says which calls change something,
which take an idempotency key (a value that lets the provider spot a
repeated request), how values are written on the wire, how errors and pages
of results come back and how webhooks are signed. You write each API's
package once, or install one someone has written, and your app connects to
it in app.jadpo.
| Topic | In short |
|---|---|
| How the pieces fit | One API called, start to finish; then what each word means, where each thing runs and what is built |
| Running a service in a container ○ not built | A provider that is a container image Jadpo starts, through Docker or Podman |
| Kinds of package | Library (types, failures, pure functions) and provider (one API); the kind follows from what is inside |
| The golden rule | A package can do nothing the app cannot, and the app can do everything a package can |
| The format | package.jadpo (licence:, jadpo:), an optional provider.jadpo, folders laid out as shared/ is, public as the API |
| Where packages live | Installed in packages/<name>/<version>/, committed, digest-checked, read-only; the app's own in shared/providers/ |
| Where they come from ▲ partly | A folder, a git tag, the OpenAPI importer, or written by hand from the docs. The public registry isn't live yet |
| The surface | surface.jadpo_record, generated and readable, pointing at each file; jadpo package show |
| Connecting | connections: in app.jadpo; built-in drivers are configured there, never packaged |
| Calling | couriers.bookings.create(request) and package actions such as stripe.start_subscription(...), from actions only, failures mapped at the call |
| Decoding | The package declares how values are written on the wire; the runtime decodes; the app translates |
| Package code | No state; package actions call only their own API; events only about the outside world; polls |
| Several calls in order | Each step recorded before it is sent, replayed on a rerun, stopped as diverged on any difference |
| Receiving | Webhooks, replies, handshakes and queues, each arriving as an event |
| Acting for each user ○ not built | OAuth grants owned by one of the app's records; on_behalf_of: on every call |
| Capabilities | Only jobs Jadpo itself does, each whole (email, files, search and the rest); the provider chosen in app.jadpo |
| Development | Provider calls faked by default, let through to the sandbox by name, every call logged |
| Tests | A generated fake per package; scheduled contract runs against the sandbox |
| How packages, connections, capabilities and services fit together Here is an app calling one outside API, with nothing left out: it books a collection with a courier. |
| Connecting and calling How an app reaches an outside service, such as a courier's API, in development, in tests and in production. |
| Receiving from outside A provider tells your app that something happened in one of two ways: it sends a webhook, or it puts a message on a queue. |
| Capabilities A capability is a job Jadpo does itself, such as storing files or sending email, done through a connection you choose. |
| Using packages partly The kinds of package, where they come from, and what a package may do in your app. |
| Writing and publishing packages partly The package format, and how you develop, verify and publish a package. |
| Running a service in a container not built A provider's API can be a stateless container image that Jadpo starts beside your app, such as Gotenberg turning HTML into PDFs or ClamAV scanning uploads. |
What is built says which of this works today.
Markdown for agents: /docs/external-services.md.Built from Jadpo main at aee2e8f.