POST /v1/spvs/{slug}/subscriptions.
Lifecycle
subscription.completed delivery
subscription.completed is eventually consistent:
- When a Zest admin marks the subscription
Completed, the system attempts to emitsubscription.completedsynchronously. - If that synchronous emit was skipped (admin path bypassed the helper, queue back-pressure, transient error), a reconciler runs on a 60-second cadence and emits the webhook for any subscription that hasn’t yet received its
subscription.completed.
- You will receive exactly one
subscription.completedper subscription, even if the synchronous path drops it. - The webhook may arrive up to ~60 seconds after the admin action, not instantly.
- Idempotency is enforced via the flag — the reconciler never double-fires.
Strict order: forms before fundings
POST .../fundings returns 409 conflict when called before POST .../forms succeeds. This enforces compliance: Zest must hold the signed subscription contract before any wire-transfer money is associated with the subscription.
If you orchestrate uploads in parallel, gate the funding upload on a successful signed-form response (or on the corresponding webhook).
Per-row payload
Each row in the bulk request carries:
The
lumpSum.value is a decimal string — never a float — to avoid binary floating-point drift on monetary amounts.
Idempotency
Idempotency-Key is optional on POST /v1/spvs/{slug}/subscriptions. Replays under the same key + same body return the cached response (24h TTL). See Idempotency.
Upload constraints
Bothforms and fundings endpoints accept multipart uploads with:
- Max size: 10 MB.
- Allowed content types:
application/pdf,image/jpeg,image/png,image/webp.
413 payload_too_large. Wrong content-type → 415 unsupported_media_type.