@@ -9,6 +9,7 @@ It provides a consistent way to configure:
99- auth
1010- lifecycle hooks
1111- request observability metadata
12+ - response validation
1213
1314## Basic client
1415
@@ -64,6 +65,7 @@ type ClientConfig = {
6465 // see Hooks section
6566 };
6667 retry? : RetryConfig ;
68+ validateResponse? : ResponseValidator ;
6769};
6870```
6971
@@ -100,7 +102,7 @@ client.request(config)
100102
101103- ` get ` and ` delete ` do not accept body
102104- ` post ` , ` put ` , and ` patch ` accept request body as the second argument
103- - ` options ` is used for headers, query, timeout, retry, and other settings
105+ - ` options ` is used for headers, query, timeout, retry, validation, idempotency keys, and other settings
104106
105107## GET request
106108
@@ -165,13 +167,17 @@ type RequestOptions = {
165167 retry? : RetryConfig ;
166168 signal? : AbortSignal ;
167169 requestId? : string ;
170+ idempotencyKey? : string ;
171+ validateResponse? : ResponseValidator ;
168172};
169173```
170174
171175` requestId ` can be provided explicitly when you want to correlate logs or trace a request across services.
172176
173177Request-level ` retry ` overrides client-level retry settings.
174178
179+ Request-level ` validateResponse ` overrides client-level response validation.
180+
175181## Low-level request
176182
177183``` ts
@@ -201,6 +207,8 @@ type RequestConfig = {
201207 retry? : RetryConfig ;
202208 signal? : AbortSignal ;
203209 requestId? : string ;
210+ idempotencyKey? : string ;
211+ validateResponse? : ResponseValidator ;
204212};
205213```
206214
@@ -258,6 +266,55 @@ await client.get('/users', {
258266});
259267```
260268
269+ ## Idempotency key
270+
271+ Use ` idempotencyKey ` for non-idempotent operations that may be retried safely.
272+
273+ ``` ts
274+ await client .post (
275+ ' /payments' ,
276+ { amount: 100 },
277+ {
278+ idempotencyKey: ' payment-123' ,
279+ },
280+ );
281+ ```
282+
283+ This adds:
284+
285+ ``` http
286+ idempotency-key: payment-123
287+ ```
288+
289+ If both ` idempotencyKey ` and an explicit ` idempotency-key ` header are provided, the explicit header takes precedence.
290+
291+ ` POST ` and ` PATCH ` requests are retried only when the method is included in ` retry.retryMethods ` and the request provides ` idempotencyKey ` .
292+
293+ ## Response validation
294+
295+ Use ` validateResponse ` to validate parsed response data before it is returned.
296+
297+ ``` ts
298+ const client = createClient ({
299+ baseUrl: ' https://api.example.com' ,
300+ validateResponse(data ) {
301+ return typeof data === ' object' && data !== null && ' id' in data ;
302+ },
303+ });
304+ ```
305+
306+ You can override validation per request:
307+
308+ ``` ts
309+ await client .get (' /users/1' , {
310+ validateResponse(data ) {
311+ return typeof data === ' object' && data !== null && ' email' in data ;
312+ },
313+ });
314+ ```
315+
316+ Returning ` false ` throws ` ValidationError ` . Returning ` true ` or ` undefined ` passes validation.
317+
261318## Request cancellation
262319
263320Requests can be cancelled using ` AbortSignal ` :
@@ -361,5 +418,6 @@ If the header value is invalid, `@dfsync/client` falls back to normal retry back
361418## Related guides
362419
363420- See ** Hooks** for lifecycle hooks and observability metadata
421+ - See ** Response Handling** for parsing and response validation
364422- See ** Retry** for retry conditions, backoff, and ` Retry-After `
365423- See ** Errors** for failure behavior and error types
0 commit comments