# Provider calls in development: `jadpo calls`

In `jadpo dev`, every provider operation is faked by default, so nothing
leaves your machine and you need no credentials. A fake answers from the
package's recordings, real answers saved with the package, where it has
some, and from generated defaults otherwise
([Provider calls in development](provider-calls-in-development.md)).

## Letting calls through to a sandbox

To use the provider's sandbox for some calls, name the operations or
resources in the connection's `development: { sandbox: [...] }`. Those go
to the sandbox, never to the live service. `jadpo dev --fake <connection>`
and `jadpo dev --sandbox <operation>` change this for one session only.

```text
$ jadpo calls
call_31  stripe.customers.create         generated   201   4 ms   req_0c02
call_32  stripe.payment_intents.create   scripted    card_declined   1 ms   req_0c02

$ jadpo calls script stripe.payment_intents.create card_declined
next call to stripe.payment_intents.create answers card_declined
```

## What is logged

Every call is logged, faked or real. The log holds the connection,
resource and operation, the input, the answer or failure in full, where the
answer came from (`recording`, `generated`, `scripted` or `sandbox`), the
attempts and retries, how long it took, and the request id and span. So
each call appears in `jadpo trace` beside the queries.

## Listing calls

`jadpo calls` lists the calls, and `--connection`, `--operation` and
`--request` narrow the list. `jadpo calls show <id>` prints one call. Both
take `--json`. The calls are kept with the last 500 timelines in
`build/dev/` and never committed.

## Scripting the next answer

`jadpo calls script <operation> <failure>` sets the next answer to an
operation, in the same form as a test's `fakes:`
([Fakes for integrations](fakes-for-integrations.md)). Your
agent can use it to walk through a failure path by hand.

Fakes keep no state. So for a flow that creates an object and then reads
it, either let both calls through to the sandbox, or script the read.

## What the call log shows in full

The log shows inputs and answers in full. Everywhere else, text in a
call's payload is hashed; this is the one exception, and it holds in
development only. Credentials and `secret: true` values are never shown.
In production, only the spans are kept, with no values
([Telemetry](telemetry.md)).

## Fake OAuth grants

`jadpo dev grants add <connection> --owner <id>` makes a fake OAuth grant,
the permission a person gives your app to act for them at a provider, for
that owner
([Acting for each user: OAuth grants](acting-for-each-user-oauth-grants.md)).

> **Built**, except `jadpo trace`, `jadpo watch call` and the request
> timelines. `jadpo dev` logs each provider call as it ends in
> `build/dev/calls.jsonl`, and logs an answer from a recording as
> `recording`. `jadpo calls` reads that file. Here is the plain list after
> one booking answered with the generated default and one scripted to find
> its slot taken:
>
> ```text
> $ jadpo calls
>   call    operation                source     answer        time  request
>   call_1  couriers.pickups.create  generated  + answered    0 ms  req_58d4
>   call_2  couriers.pickups.create  scripted   x slot_taken  0 ms  req_9588
>
> calls: 2 calls, 1 answered, 1 failed
>
> next: jadpo calls show call_2  shows what was sent and what came back
> ```
>
> In a terminal, the answers are `✓ answered` and `✗ slot_taken` in their
> colours, and the footer reads `✓ 2 calls  1 answered · 1 failed`. One
> call shown in full, with its request as made and its answer laid out one
> member to a line:
>
> ```text
> $ jadpo calls show call_2
> `couriers.pickups.create` failed with `slot_taken`
>     call     call_2
>     source   scripted
>     request  req_9588e1fb3505d4a7
>     at       2026-10-20T06:34:34.202Z
>     time     0 ms
>
> sent
>   POST https://sandbox.swift-couriers.example/v1/pickups
>   {
>     "postcode": "N1 9GU",
>     "slot": "pm"
>   }
>
> $ jadpo calls script couriers.pickups.create slot_taken
> Scripted `slot_taken` for the next call to `couriers.pickups.create`
>
> next: jadpo calls  shows the call once the app makes it
> ```
>
> The request id in the list is shortened as `jadpo dev`'s request lines
> shorten it, and `--request` takes any start of it. With no calls yet,
> the list says `No calls yet` and points at `jadpo dev`. With filters
> that match nothing, it says `No calls match` and repeats the filters.
> The [design notes for integrations](https://github.com/jadpo-dev/jadpo/blob/main/docs/language/notes/11-integrations.md) record the
> choices behind the development call log.
