coinbase / coinbase/cdp-sdk

Bazaar: pathParams is published as the URL-encoded route template, not the concrete value

Open
#787 0 comments 0 reactions 1 assignee Claimed by @CarsonRoscoe View on GitHub
Dominant language
Python
Stars
200
Forks
191
Avg merge
6h 16m
Merged PRs (30d)
17

Description

### Summary

For parameterized routes, the Bazaar catalog stores `extensions.bazaar.info.input.pathParams`
as the **URL-encoded route template** (`{"siren": "%7Bsiren%7D"}`), not the concrete
value the docs promise. `queryParams` on the very same resource is correct.

`docs/extensions/bazaar.mdx` (Dynamic Routes) states:

> The extension automatically extracts concrete parameter values into `pathParams`
> (e.g., `{ "userId": "123" }`)

That is not what lands in the catalog, and the effect is visible to buyers:
`agentic.market` renders `example: %7Bsiren%7D` for every path parameter and shows
an empty `description` for it, so the only sample value an agent can read is a
placeholder. The suggested call on our service page is
`npx awal x402 pay "https://api.sirenic.eu/v1/acheteur/{siret}/profil"` — a URL that
cannot succeed.

### Reproduction (all four checks on 2026-08-23, re-checked 2026-08-24)

Resource: `https://api.sirenic.eu/v1/entreprise/:siren` (mainnet, CDP facilitator,
`@x402/extensions` 2.23.0).

1. **We publish concrete example URLs.** `GET https://api.sirenic.eu/.well-known/x402`
returns 78 items, all with concrete resources — e.g.
`https://api.sirenic.eu/v1/entreprise/552032534`. Zero templates.

2. **Real settlements carry a real value.** Six settled calls on 2026-08-21
between 07:50:03 and 07:51:33 UTC, each with `{"siren": "552032534"}`
(Luhn-valid SIREN for DANONE).

3. **The catalog entry was refreshed at that exact moment, and `queryParams`
kept our declared value:**

```json
// GET /platform/v2/x402/discovery/search?query=French%20company%20registry
{
"resource": "https://api.sirenic.eu/v1/entreprise/:siren",
"lastUpdated": "2026-08-21T07:51:31.83Z",
"quality": { "lastCalledAt": "2026-08-21T07:51:33.683Z" },
"extensions": { "bazaar": { "info": { "input": {
"method": "GET",
"pathParams": { "siren": "%7Bsiren%7D" }, // <-- template, URL-encoded
"queryParams": { "geo": "true" } // <-- our declared example, correct
} } } }
}
```

4. **Three days later (2026-08-24) it is unchanged** — same `pathParams`, `lastUpdated`
still `2026-08-21T07:51:31.83Z` — so this is not a propagation delay.

The `schema` block of the same entry documents the right value
(`"9-digit SIREN (Luhn-checked; 400 otherwise), e.g. 552032534"`), which makes the
`pathParams` value internally inconsistent with the schema shipped beside it.

### Scope — who this hits

Measured over the whole `api.agentic.market` catalog on 2026-08-23 (2,349 services, 1,551
path parameters): **1,456 (94 %) expose a usable example, 94 expose a placeholder, 1 is
empty**. Of those 94 placeholders, **73 are ours** (78 %) — we are simply the most
path-parameterized service in the catalog (79 endpoints, 64 of them with a path
parameter), so the defect concentrates on us. Any registry-style API (lookup by
identifier) hits it the same way. Re-checked 2026-08-24: all 73 still render
`example: %7B...%7D` with an empty `description`.

The split inside our own service is the cleanest evidence that this is not a
publishing mistake on our side — same server, same declaration mechanism, same
deploy:

| our parameters | usable example | placeholder |
|---|---|---|
| query (37) | **37** | 0 |
| path (73) | **0** | 73 |

### Why the documented workaround doesn't cover it

We already repeat the example identifier inside each parameter's `description` in
`pathParamsSchema`, precisely because the value is overwritten. That survives in the
Bazaar `schema` object — but `api.agentic.market` renders `parameters[].description`
as `""` and only surfaces `example`, so on the surface the official
`agentic.market/SKILL.md` sends agents to, the hint is invisible.

### What we'd expect

Either of these fixes the buyer-visible outcome:

1. `pathParams` carries the concrete value from the settled request, as
`bazaar.mdx` describes (and as `queryParams` already does); or
2. failing that, the catalog prefers the `pathParams` value the resource server
declares in `extensions.bazaar.info.input` over the crawled template.

A third, independent improvement: `agentic.market` could fall back to
`schema.properties.input.pathParams..description` when `example` is a
template, and render parameter descriptions instead of dropping them.

### Minor, same surface

`agentic.market/SKILL.md` — the discovery step it hands to agents — instructs:

```
curl -sS "https://api.agentic.market/v1/services/"
```

That path **404s** (`{"code":5,"message":"Not Found"}`); the working form is
`/v1/services` without the trailing slash (re-checked 2026-08-24). Same for step 4 of
the MCP path, which names `https://api.agentic.market/v1/services/`.

### Environment

- Facilitator: CDP (mainnet, `eip155:8453`), `@x402/core` / `@x402/extensions` 2.23.0
- Resource server: first-party, no proxy, 79 indexed resources, 0 curated
- Related: #785 (`GET /x402/discovery/bundles` → 500, still open, no response since 2026-08-21)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.