# External services

[Call an outside API](/guides/guide-call-an-outside-api.md) 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](/docs/built-in-services.md), 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](/docs/running-a-service-in-a-container.md).

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](/docs/running-a-service-in-a-container.md) ○ 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](/docs/where-packages-come-from.md) ▲ 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](/docs/oauth-grants.md) ○ 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 |

| Page | What it covers |
|---|---|
| [How packages, connections, capabilities and services fit together](/docs/how-integrations-fit-together.md) | Here is an app calling one outside API, with nothing left out: it books a collection with a courier. |
| [Connecting and calling](/docs/connecting-and-calling.md) | How an app reaches an outside service, such as a courier's API, in development, in tests and in production. |
| [Receiving from outside](/docs/receiving-from-outside.md) | 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](/docs/capabilities.md) | A capability is a job Jadpo does itself, such as storing files or sending email, done through a connection you choose. |
| [Using packages](/docs/using-packages.md) ▲ partly | The kinds of package, where they come from, and what a package may do in your app. |
| [Writing and publishing packages](/docs/writing-and-publishing-packages.md) ▲ partly | The package format, and how you develop, verify and publish a package. |
| [Running a service in a container](/docs/running-a-service-in-a-container.md) ○ 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](/docs/external-services-built.md) says which of this works today.
