The Zest Partner API supports idempotency on every write endpoint via theDocumentation Index
Fetch the complete documentation index at: https://docs.zestequity.com/llms.txt
Use this file to discover all available pages before exploring further.
Idempotency-Key request header. Idempotency lets you safely retry network failures without risking duplicate side effects.
Required vs optional
| Endpoint | Idempotency-Key |
|---|---|
POST /v1/spv-requests | Required. Returns 400 invalid_request if missing. |
POST /v1/investors | Optional (additionally idempotent on partnerInvestorId). |
POST /v1/spvs/{slug}/subscriptions | Optional. |
POST /v1/spvs/{slug}/subscription/{personId}/forms | Not used (uploads are content-addressed). |
POST /v1/spvs/{slug}/subscription/{personId}/fundings | Not used (uploads are content-addressed). |
Semantics
When you submit a request withIdempotency-Key: <key>:
- Zest hashes the canonicalised request body (sorted JSON keys, UTF-8).
- First call with that key + body hash:
- The request executes normally.
- The response is cached for 24 hours keyed by
(client_id, key).
- Replay (same key + same body hash within 24h):
- Zest returns the cached response verbatim, with the original
200/201status. - No side effects on the resource.
- Zest returns the cached response verbatim, with the original
- Conflict (same key + different body hash within 24h):
- Zest returns
409 conflict, codeconflict. - The original request is left untouched.
- Zest returns
Generating keys
A v4 UUID is the simplest choice — collision probability is negligible.Python
Node.js
Best practices
- One key per logical request. Generate the key when the user clicks Submit, not on every retry — that way every retry of the same logical request shares a key.
- Persist the key with the request in your database. After a network failure, retry with the same key. Don’t lose the key between retries.
- Don’t mutate the request body across retries. A different body hash with the same key returns
409. If the body genuinely needs to change, generate a new key. - Treat the response as authoritative. Zest replays the original status code; don’t conditionalise on
2xx-vs-201.
TTL & cache scope
- TTL: 24 hours from the first call.
- Scope:
(client_id, idempotency_key). Two different partner applications can use the same key without collision. - Storage: Redis. Cache miss falls back to a real execution, so very rare key drops are bounded by re-running the request — exactly the same outcome as the first call would have produced.
Investor-row idempotency (different layer)
POST /v1/investors carries a second layer of idempotency: the partnerInvestorId field. Replaying the same partnerInvestorId always returns the existing Zest person id, regardless of whether you also supplied an Idempotency-Key. This makes long-running bulk loads safe across crashes.
What to do on 409 conflict
- Confirm you intended a new request — generate a fresh key and resubmit.
- If you intended to replay the original — fix the body to match what you sent before, or contact
partners@zestequity.comwith theerrorIdfor support to inspect.