Skip to content

Commit 2081fa6

Browse files
committed
docs: align book + README with current code semantics
Sweep through the lies surfaced by the staleness audit: - README: drop /health version claim; rewrite "Control encoding at request time" tagline to reflect the operator-opt-in `'*'` model. - CLAUDE.md: routes list now includes /requests/{id} and notes /health no longer exposes version; pipeline auth step lists all three methods (free / apiKey / x402); config-format paragraph reflects required fields and the encoding `'*'` semantics. - book/docs/concepts/endpoint-ids.md: drop the obsolete "operator omitted → client fills in" mode; document type/path required, `'*'` wildcard sentinel, silently-ignored pinned fields, and 400 on missing wildcard request param. - book/docs/consumers/getting-started.md: rewrite "choosing encoding at request time" around the wildcard model; per-field 400 error rows in the error table; drop the /health version field. - book/docs/troubleshooting.md: replace the old "Both _type and _path required" entry with the per-field "Endpoint requires `_type` request parameter" form (and `_path` / `_times`). - book/docs/concepts/fhe-encryption.md: encrypt endpoints must pin every encoding field; the schema rejects `'*'` for FHE. No code changes — pure doc-to-code reconciliation.
1 parent ce3959e commit 2081fa6

4 files changed

Lines changed: 66 additions & 48 deletions

File tree

book/docs/concepts/endpoint-ids.md

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -57,23 +57,27 @@ One upstream API usually serves many different consumers. A CoinGecko price endp
5757
for a lending protocol, as `uint128 × 1e8` for a DEX, or read for its `last_updated_at` timestamp by a staleness check.
5858
These are legitimate, simultaneous uses of the same HTTP call.
5959

60-
Airnode supports this by letting the operator decide **per field** whether to fix a value or leave it client-controlled.
61-
Clients fill unfixed fields at request time via reserved parameters `_type`, `_path`, and `_times` in the request body.
62-
The endpoint ID commits to exactly which fields were fixed and which were left openany field the operator did not fix
63-
in config is encoded as `*` in the canonical string.
60+
Airnode supports this by letting the operator decide **per field** whether to pin a concrete value or open it to the
61+
client via the literal wildcard `'*'`. Wildcard fields are filled at request time via reserved parameters `_type`,
62+
`_path`, and `_times` in the request body. The endpoint ID commits to the exact splitwhatever the operator wrote
63+
flows through to the canonical string verbatim, so a `'*'` in config means `*` in the ID.
6464

65-
Four common configurations:
65+
`type` and `path` are required whenever an `encoding` block is present. `times` is optional and only valid for numeric
66+
types (`int256` / `uint256`).
6667

67-
| Operator config | Encoding spec in ID | Who controls what |
68-
| -------------------------------------------------------- | --------------------------------------------- | ----------------------------------------------------- |
69-
| `encoding: { type, path, times }` — all three fields set | `type=int256,path=$.price,times=1e18` | Fully operator-fixed |
70-
| `encoding: { type, times }` — type and multiplier only | `type=int256,path=*,times=1e18` | Operator fixes type & multiplier; client chooses path |
71-
| `encoding: {}` — block present, no fields set | `type=*,path=*,times=*` | Client fully controls encoding |
72-
| No `encoding` block at all | (encoding spec omitted from canonical string) | Endpoint returns raw-JSON-hash responses only |
68+
Three valid configurations:
7369

74-
Client-supplied fields **cannot override** operator-fixed values. If the operator sets `type: int256`, the request's
75-
`_type` parameter is ignored for encoding (though it still counts as a request parameter). The operator's fixes are
76-
authoritative.
70+
| Operator config | Encoding spec in ID | Who controls what |
71+
| ------------------------------------------------------------------------------------- | --------------------------------------------- | ----------------------------------------------------- |
72+
| `encoding: { type: int256, path: $.price, times: '1e18' }` — fully pinned | `type=int256,path=$.price,times=1e18` | Fully operator-fixed |
73+
| `encoding: { type: int256, path: '*', times: '1e18' }` — pin type & multiplier | `type=int256,path=*,times=1e18` | Operator fixes type & multiplier; client chooses path |
74+
| `encoding: { type: '*', path: '*', times: '*' }` — all wildcards (fully open) | `type=*,path=*,times=*` | Client fully controls encoding |
75+
| No `encoding` block at all | (encoding spec omitted from canonical string) | Endpoint returns raw-JSON-hash responses only |
76+
77+
Client-supplied fields are **silently ignored** for any field the operator pinned. If the operator sets
78+
`type: int256`, the request's `_type` parameter has no effect on encoding (it's still consumed by the pipeline and never
79+
sent to the upstream API). Wildcard fields require the matching reserved parameter: omitting `_path` on an endpoint
80+
with `path: '*'` returns 400.
7781

7882
### FHE-encrypted endpoints
7983

@@ -133,12 +137,13 @@ silently alter the trust split of an existing endpoint.
133137
### Endpoints with no `encoding` block
134138

135139
An endpoint with no `encoding` block in config does not include an encoding spec in the canonical string. Its signature
136-
covers `keccak256(json_hash)` of the raw upstream response when called without request-side encoding parameters.
140+
covers `keccak256(json_hash)` of the raw upstream response. Reserved request parameters cannot synthesize an encoding
141+
out of nothing — `_type` / `_path` / `_times` are ignored in raw mode, so the only way to ABI-encode a response is for
142+
the operator to declare an `encoding` block (pinned or wildcarded).
137143

138-
Note that the canonical string for such an endpoint carries **no commitment to encoding** at all — not even a wildcard.
139-
If a consumer contract wants a guarantee that the ID binds the response shape, the operator should declare at least an
140-
empty `encoding: {}` block, which puts `type=*,path=*,times=*` into the ID. An endpoint without any `encoding` block
141-
should be treated as raw-JSON-only from a consumer perspective.
144+
If a consumer contract wants the endpoint ID to bind some encoding shape, the operator should declare an `encoding`
145+
block with the appropriate pin/wildcard split. An endpoint without any `encoding` block should be treated as
146+
raw-JSON-only from a consumer perspective.
142147

143148
## What Is Included
144149

book/docs/concepts/fhe-encryption.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,9 +206,10 @@ encrypted. The auction contract compares `FHE.gt(bid, reservePrice)` without rev
206206
on-chain submission of a cached ciphertext succeeds; the rest revert "already fulfilled". A cache on an encrypt
207207
endpoint therefore both serves stale data and caps on-chain ingestion to one submission per window. Leave `cache`
208208
unset unless that's actually what you want.
209-
- **Set `encoding.times` explicitly.** If you omit `encoding.times`, the requester controls the scale multiplier via the
210-
`_times` parameter (and the endpoint ID records `times=*`). For an encrypt endpoint you almost always want a fixed
211-
scale — set `times: '1'` if you mean "no scaling".
209+
- **Pin every encoding field.** The schema rejects an `encrypt` endpoint whose encoding contains a `'*'` wildcard — an
210+
operator approving FHE-encrypted output is approving a specific shape, so `type`, `path`, and `times` must all be
211+
concrete values. Omit `times` entirely if the upstream value is already an integer (it means "no multiplier"); set
212+
`times: '1e18'` (or similar) for float-shaped upstream data.
212213
- **Throughput.** The Zama coprocessor currently handles a limited number of input verifications per second.
213214
High-frequency price feeds may hit this limit.
214215
- **Numeric, encoded responses only.** `encrypt` requires an `encoding` block producing a single `int256`/`uint256`

book/docs/consumers/getting-started.md

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ curl http://airnode.example.com/health
1616
```json
1717
{
1818
"status": "ok",
19-
"version": "2.0.0",
2019
"airnode": "0xd1e98F3Ac20DA5e4da874723517c914a31b0e857"
2120
}
2221
```
@@ -147,38 +146,44 @@ examples using AirnodeVerifier.
147146

148147
## Choosing encoding at request time
149148

150-
Some endpoints leave encoding unset, letting the client choose at request time. Pass reserved parameters in the request
151-
body:
149+
Some endpoints mark one or more encoding fields with the wildcard `'*'`, letting the client choose them per request.
150+
Supply the matching reserved parameter in the request body for each `'*'` field:
152151

153152
```json
154153
{
155154
"parameters": {
156155
"ids": "ethereum",
157156
"vs_currencies": "usd",
158157
"_type": "int256",
159-
"_path": "ethereum.usd",
160-
"_times": "1000000000000000000"
158+
"_path": "$.ethereum.usd",
159+
"_times": "1e18"
161160
}
162161
}
163162
```
164163

165-
- `_type` -- the Solidity ABI type to encode as (`int256`, `uint256`, `bool`, `bytes32`, `address`, `string`, `bytes`)
166-
- `_path` -- dot-separated JSON path to extract from the upstream response
167-
- `_times` -- multiplier applied before encoding (use `1e18` for 18 decimal precision)
164+
- `_type` -- the Solidity ABI type to encode as (`int256`, `uint256`, `bool`, `bytes32`, `address`, `string`, `bytes`).
165+
Only consumed when the operator set `encoding.type: '*'`.
166+
- `_path` -- JSONPath expression to extract from the upstream response. Only consumed when `encoding.path: '*'`.
167+
- `_times` -- multiplier applied before encoding (numeric types only). Only consumed when `encoding.times: '*'`.
168168

169-
Both `_type` and `_path` are required together. `_times` is optional and defaults to no multiplication.
169+
If a wildcard field's matching reserved parameter is missing, the server returns 400. If the operator pinned a field
170+
(concrete value rather than `'*'`), any client-supplied reserved parameter for it is silently ignored — the operator's
171+
value wins. Endpoints with no `encoding` block at all return raw JSON; reserved parameters cannot synthesize encoding
172+
out of nothing.
170173

171174
## What can go wrong
172175

173-
| Status | Error | What to do |
174-
| ------ | ------------------------------------------------ | ------------------------------------------------------------------------------- |
175-
| `400` | `Missing required parameter(s): X` | Add the missing parameters to your request body. |
176-
| `400` | `Both _type and _path are required for encoding` | You sent one reserved parameter without the other. Send both or neither. |
177-
| `401` | `Missing X-Api-Key header` | The endpoint requires authentication. Add `X-Api-Key: your-key` to the request. |
178-
| `401` | `Invalid API key` | The key value is wrong. Check with the airnode operator. |
179-
| `404` | `Endpoint not found` | The endpoint ID is incorrect. Verify the ID with the operator. |
180-
| `413` | `Request body too large` | The request body exceeds 64KB. Reduce the payload size. |
181-
| `415` | `Content-Type must be application/json` | Set `Content-Type: application/json`. |
182-
| `429` | `Too Many Requests` | Wait and retry. The airnode has a request rate limit configured. |
183-
| `502` | `API call failed` | The upstream API is unreachable or returning errors. Try again later. |
184-
| `502` | `No value found at path: $.X` | The upstream response shape changed or the path is wrong. Contact the operator. |
176+
| Status | Error | What to do |
177+
| ------ | ---------------------------------------------------- | ----------------------------------------------------------------------------------------- |
178+
| `400` | `Missing required parameter(s): X` | Add the missing parameters to your request body. |
179+
| `400` | `` Endpoint requires `_type` request parameter `` | The operator marked `type: '*'`. Supply `_type` in `parameters`. |
180+
| `400` | `` Endpoint requires `_path` request parameter `` | The operator marked `path: '*'`. Supply `_path` in `parameters`. |
181+
| `400` | `` Endpoint requires `_times` request parameter `` | The operator marked `times: '*'`. Supply `_times` in `parameters`. |
182+
| `401` | `Missing X-Api-Key header` | The endpoint requires authentication. Add `X-Api-Key: your-key` to the request. |
183+
| `401` | `Invalid API key` | The key value is wrong. Check with the airnode operator. |
184+
| `404` | `Endpoint not found` | The endpoint ID is incorrect. Verify the ID with the operator. |
185+
| `413` | `Request body too large` | The request body exceeds 64KB. Reduce the payload size. |
186+
| `415` | `Content-Type must be application/json` | Set `Content-Type: application/json`. |
187+
| `429` | `Too Many Requests` | Wait and retry. The airnode has a request rate limit configured. |
188+
| `502` | `API call failed` | The upstream API is unreachable or returning errors. Try again later. |
189+
| `502` | `No value found at path: $.X` | The upstream response shape changed or the path is wrong. Contact the operator. |

book/docs/troubleshooting.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,24 +95,31 @@ curl -X POST http://airnode.example.com/endpoints/0x... \
9595
**Fix:** Include all required parameters in the `parameters` object of the request body. Check the endpoint
9696
specification for the full parameter list.
9797

98-
### `Both _type and _path are required for encoding` (400)
98+
### ``Endpoint requires `_type` request parameter`` (400)
9999

100-
**Cause:** The request includes `_type` without `_path` or vice versa. These reserved parameters must be sent together.
100+
(Or `` `_path` ``, or `` `_times` ``.)
101101

102-
**Fix:** Send both `_type` and `_path`, or omit both to get a raw JSON response.
102+
**Cause:** The operator marked one or more encoding fields with the wildcard `'*'`. Each wildcard field requires the
103+
matching reserved parameter (`_type` / `_path` / `_times`) in the request body. This 400 means at least one is missing.
104+
105+
**Fix:** Supply every wildcarded field. The operator's documentation should list which fields are wildcarded — they
106+
correspond to whichever ones appear as `*` in the canonical endpoint spec.
103107

104108
```json
105109
{
106110
"parameters": {
107111
"ids": "ethereum",
108112
"vs_currencies": "usd",
109113
"_type": "int256",
110-
"_path": "ethereum.usd",
111-
"_times": "1000000000000000000"
114+
"_path": "$.ethereum.usd",
115+
"_times": "1e18"
112116
}
113117
}
114118
```
115119

120+
If the operator pinned a field, any reserved parameter you send for that field is silently ignored — the operator's
121+
value wins. If the endpoint has no `encoding` block at all, you'll get raw JSON back regardless of reserved parameters.
122+
116123
### `Request body too large` (413)
117124

118125
**Cause:** The request body exceeds the size limit. Airnode allows up to 64KB.

0 commit comments

Comments
 (0)