Manage contacts, offers and webhook endpoints with the signed-in JSON API

The JSON API that works with your own sign-in instead of a key: how to call it, what each role can do, and the contacts, offers and webhook endpoint requests.

Besides the key-based API, the admin app has a JSON API that works with your own sign-in. Some admin screens use it behind the scenes, such as the contacts list's quick view and an offer's purchases export. You can also call it from a browser where you're signed in, to script bulk changes. This article covers contacts, offers and webhook endpoints; products, modules, lessons and enrollments are in Build courses with the signed-in JSON API.

Who can do this

It works only with a signed-in session on https://app.zinstruct.com. An API key doesn't work here: a request with only a key gets "Authentication required". These requests aren't in the API reference. What you can do depends on your role:

  • Read contacts and offers: any team member (owner, admin, staff or viewer).
  • Create and update contacts: staff, admins and the owner.
  • Delete contacts, and create, update or delete offers: admins and the owner.
  • Read, add, change or delete webhook endpoints: admins and the owner. Staff and viewers get an empty list, and "Endpoint not found" for a single endpoint. Adding an endpoint also needs the Professional plan, the same as the form on Settings → Webhooks.
  • Anyone refused gets 403 with "Not allowed".
  • In a read-only workspace (after a free trial ends), requests that change data get a 402 page titled "Your free trial has ended".

Send a request

  1. Sign in to the admin app at https://app.zinstruct.com in your browser.
  2. From that browser, for example its developer console on an admin page, send requests to paths that start with /api/v1/. Your sign-in goes with them automatically.
  3. Send any body as JSON.
  4. A successful reply wraps the result in data: { "data": { … } }. A list adds page: { "data": [ … ], "page": { "next": "…", "limit": 50 } }.
  5. For the next page of a list, pass the next value back as ?cursor=, and set the size with ?limit= (1 to 100, default 50). When next is null, you've reached the end.

Errors come back as { "error": { "code": "…", "message": "…", "details": … } }.

Contacts

  • GET /api/v1/contacts: list contacts, newest first, a page at a time.
  • GET /api/v1/contacts/{id}: one contact.
  • GET /api/v1/contacts/{id}/summary: the numbers the contacts list's quick view shows, such as revenue, offers and products, sign-ins, status and tags.
  • POST /api/v1/contacts: add a contact. email is required; you can also send first_name, last_name, name, phone, mobile_phone, comment, marketing_status (subscribed or unsubscribed), newsletter_subscribed and source.
  • PATCH /api/v1/contacts/{id}: change any of those fields (send at least one).
  • DELETE /api/v1/contacts/{id}: delete a contact. It also removes their access to your products; their past sales stay in your records.
The contact quick view drawer, which shows the contact summary this API returns

Offers

  • GET /api/v1/offers: your newest 200 offers, each with its product. This list has no pages.
  • GET /api/v1/offers/{id}: one offer and its product.
  • POST /api/v1/offers and PATCH /api/v1/offers/{id}: create or change an offer. The body is checked by the same rules as the offer form; the main fields are product_id, name, price_cents and plan (one_time, subscription, payment_plan or free).
  • DELETE /api/v1/offers/{id}: delete an offer. Past sales stay in your records.
  • GET /api/v1/offers/{id}/export: a CSV of the offer's purchases with Date, Status, Kind, Amount, Currency, Email and Reference. This is the Export item in an offer's More actions (⋮) menu, and any team member can use it.
An offer page with the More actions menu open on Duplicate, Export and Delete

Webhook endpoints

  • GET /api/v1/webhooks and GET /api/v1/webhooks/{id}: your endpoints, without their signing secrets.
  • GET /api/v1/webhooks/event-types: every event you can subscribe to, in groups, with the payload version. Anyone signed in can read it.
  • POST /api/v1/webhooks: add an endpoint with url, and optionally description and event_types (leave it empty for all events). Your plan must include webhooks (Professional). The reply includes secret. It's the only reply that does, so store it.
  • PATCH /api/v1/webhooks/{id}: change description, event_types or status (active or disabled).
  • DELETE /api/v1/webhooks/{id}: delete an endpoint and its delivery log. The reply is { "data": { "deleted": true } }.

If your Webhooks page shows the hosted webhook portal, these requests keep the portal in step:

  • An endpoint you add here is added to the portal too and receives events. The secret in the reply is the portal's signing secret for it, so check the svix-signature header with it.
  • A change or delete here is made in the portal first.
  • If the portal refuses an add, change or delete, nothing is saved or changed, and you get a 500 (see below). Try again.

What happens next

  • Adding, changing or deleting a contact sends contact.created, contact.updated or contact.deleted to your webhooks. Those events carry only the contact's id and your workspace's id.
  • Creating or changing an offer sends offer.created or offer.updated. Deleting an offer sends nothing.
  • Webhook endpoint changes send no events, and nothing here sends an email.

Common errors

  • "Authentication required" (401): you're not signed in in this browser, or you sent an API key instead.
  • "Not allowed" (403): your role can't do this. Ask an admin or the owner.
  • "Webhooks is included from the Professional plan up. Subscribe in Settings → Billing to unlock it." (403, plan_required): you tried to add a webhook endpoint on a plan without webhooks. See Plans and billing.
  • "Request validation failed" (400): the body isn't valid JSON, or a field is wrong; details says which. For offers it can include "A payment plan needs at least 2 installments." or "A paid price must be at least $0.99, or set it to $0 for a free offer." An empty change gives "At least one field is required".
  • "A contact with this email already exists" (409): use the existing contact, or change the email.
  • "Contact not found", "Offer not found" or "Endpoint not found" (404): the id is wrong, or belongs to another workspace.
  • "Endpoint URL must use https" and the other address messages from Set up webhooks appear under details when you add an endpoint.
  • "Could not register the endpoint with the webhook service. Nothing was saved — try again." (500): on an account with the hosted webhook portal, the portal refused the new endpoint. Nothing was added; send the request again.
  • "Could not update the endpoint in the webhook service. Nothing was changed — try again." (500): the portal refused a change or delete. The endpoint is as it was; send the request again.
  • "Something went wrong" (500): try again.
  • "Your free trial has ended" (402 page): the workspace is read-only. Choose a plan to make changes.

Related articles

Still stuck? Talk to a human.

Email support@zinstruct.com. We reply within one business day, Monday to Friday, 9 a.m. to 5 p.m. US Mountain Time. Already signed in? Ask from the help button inside the app.

Email support