Documentation Index
Fetch the complete documentation index at: https://docs.zestequity.com/llms.txt
Use this file to discover all available pages before exploring further.
The examples below use http://localhost:8080 as the API base URL for local development against the open-source reference implementation. Production base URLs (sandbox + live) are communicated during partner onboarding.
This walkthrough creates an SPV request end to end using the sandbox environment. By the end you will have:
- Exchanged a partner JWT for an access token.
- Listed available contract templates.
- Submitted an SPV creation request with
Idempotency-Key.
- Verified the resulting
spv_request.created webhook.
You need a sandbox client_id, the matching EdDSA private key, and a registered webhook URL + signing secret. Email partners@zestequity.com to provision.
1. Mint a JWT assertion
Build a JWT with the following claims:
| Claim | Value |
|---|
iss | Your API base URL |
sub | Your client_id |
aud | https://sandbox.api.zestequity.com |
client_id | Your client_id |
iat | now (unix seconds) |
exp | now + 60 |
Sign it with EdDSA using the private key registered with Zest.
2. Exchange it for an access token
curl -X POST https://sandbox.api.zestequity.com/v1/oauth2/tokens \
-H "Accept: application/json" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer" \
-d "assertion=<JWT>"
Response:
{
"accessToken": "eyJ...",
"tokenType": "Bearer",
"expiresIn": 3600
}
3. Submit an SPV request
curl -X POST https://sandbox.api.zestequity.com/v1/spv-requests \
-H "Accept: application/json" \
-H "Authorization: Bearer eyJ..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"templateId": "syndicate_secondary",
"templateVersion": "1.0.0",
"attributes": {
"underlyingCompanySlug": "co_acme",
"currency": "USD",
"shareClasses": [
{
"name": "Class A",
"managementFeePercent": "2.0",
"carryPercent": "20.0"
}
]
}
}'
Successful response (201 Created):
{
"spvRequestSlug": "svr_a1b2c3",
"status": "pending-review",
"templateId": "syndicate_secondary",
"templateVersion": "1.0.0",
"tenantSlug": "acme",
"clientId": "client_xyz",
"attributes": { "...": "..." },
"createdAt": "2026-05-07T12:00:00Z",
"updatedAt": "2026-05-07T12:00:00Z"
}
4. Same call in Python
import os
import uuid
import time
import jwt
import requests
CLIENT_ID = os.environ["ZEST_CLIENT_ID"]
PRIVATE_KEY = open(os.environ["ZEST_PRIVATE_KEY_PATH"]).read()
BASE_URL = "https://sandbox.api.zestequity.com"
now = int(time.time())
assertion = jwt.encode(
{
"iss": "https://your-api.example.com",
"sub": CLIENT_ID,
"aud": BASE_URL,
"client_id": CLIENT_ID,
"iat": now,
"exp": now + 60,
},
PRIVATE_KEY,
algorithm="EdDSA",
)
token = requests.post(
f"{BASE_URL}/v1/oauth2/tokens",
data={
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": assertion,
},
).json()["accessToken"]
resp = requests.post(
f"{BASE_URL}/v1/spv-requests",
headers={
"Authorization": f"Bearer {token}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"templateId": "syndicate_secondary",
"templateVersion": "1.0.0",
"attributes": {
"underlyingCompanySlug": "co_acme",
"currency": "USD",
"shareClasses": [
{"name": "Class A", "managementFeePercent": "2.0", "carryPercent": "20.0"}
],
},
},
)
print(resp.status_code, resp.json())
5. Verify the webhook
You should receive a POST to your webhook URL with body:
{
"eventId": "wde_...",
"eventType": "spv_request.created",
"occurredAt": "2026-05-07T12:00:00Z",
"data": {
"spvRequestSlug": "svr_a1b2c3",
"templateId": "syndicate_secondary",
"templateVersion": "1.0.0",
"tenantSlug": "acme",
"attributes": { "...": "..." },
"status": "pending-review"
}
}
Verify the Zest-Signature header before processing — see Verification.
Next steps