teachable.expert
Teachable Webhook Events: A Field Guide to Payloads, Gaps, and Workaroundswebhooks

Teachable Webhook Events: A Field Guide to Payloads, Gaps, and Workarounds

A practical reference for developers building on Teachable webhooks — what each event actually sends, where the payload data is inconsistent, and how to build reliable infrastructure around the gaps.

webhooksapiinfrastructure

All 20 V1 Teachable Webhooks are covered in this article. To find out more about a specific webhook, use the links below or scroll down to the start of the article

Enrollment events

Sale & transaction events

User events

Tagging events

Content & engagement events

Intro

Open with the moment every developer hits: you've set up a webhook listener, Teachable fires an event, and you start building your handler based on what you received. Three events later you realise the payload structure isn't what you expected — a field that was there before is missing, something is always null, and there's no documentation explaining why. This is the article that should have existed before you started. A field-level reference for what Teachable's webhooks actually send, where the data is inconsistent across event types, and how to write handlers that don't break when the payload doesn't match your assumptions.

Section 1 — How Teachable webhooks work (school owner accessible, ~200 words)

Quick conceptual grounding before the technical depth. Explain the event-driven model in plain language:

  • Something happens in your school — a student enrolls, a sale completes, a comment is posted
  • Teachable sends an HTTP POST to a URL you've configured
  • Your server receives the payload and does something with it — updates a CRM, triggers an email, logs to a database

One paragraph on why this matters for school owners: webhooks are how you connect Teachable to everything else. If your CRM isn't updating when students enroll, or your reporting is always a step behind, webhooks are the mechanism that fixes that — when they're implemented correctly. One honest note: unlike some platforms, Teachable doesn't sign its webhook payloads with a signature header. That means your endpoint can't cryptographically verify that a request genuinely came from Teachable. Flag this here, expand in section 4.

Section 2 — The full event list (reference section, scannable)

A clean reference table of every available webhook event. Something like:

Event Trigger
enrollment.created Student is enrolled in a course
enrollment.completed Student completes a course
sale.created A purchase is made
comment.created A student posts a comment
user.created A new user account is created
lesson.completed A student completes a lesson

Add any others you know from experience. Flag any that are undocumented or behave unexpectedly — even a brief note in the table is more than anyone else has published.

Section 3 — The payload inconsistency problem (the core of the article)

This is the section that makes the article worth bookmarking. Structure it event-by-event or field-by-field depending on what's clearest — I'd suggest event-by-event since that's how a developer will be reading it (they're handling a specific event and want to know what they'll get). Key points to cover from what you know: enrollment.completed and enrollment.created — include last_ip and current_ip, and last_four which is always null. Worth noting explicitly:

{
"last_four": null,
"current_ip": "203.0.113.42",
"last_ip": "203.0.113.41"
}

Add a note: last_four appears to be a legacy field retained from an earlier version of the API. Don't build any logic that depends on it containing a value — it won't. comment.created and sale.created — no IP data. For sale.created specifically this is a genuine gap — knowing the IP of a purchaser has legitimate fraud detection use cases and it simply isn't there. For each inconsistency, follow this pattern:

  1. What you'd expect to be there
  2. What's actually there
  3. What that means for your handler
  4. The workaround if one exists

Section 4 — What Teachable webhooks don't do (the honest list)

This is your Section 4 equivalent from the B2B article — the limitations stated plainly. Based on what you know, likely includes:

No signature verification. Teachable doesn't send a signature header with webhook payloads. Any system that knows your endpoint URL can send a fake payload and your handler will process it. The workaround is a shared secret token as a query parameter or header that you validate on your side — not cryptographically perfect but significantly better than nothing.

No guaranteed delivery. Teachable will retry failed webhook deliveries but the retry logic isn't publicly documented — how many times, at what intervals, whether there's a dead letter mechanism. Build your handlers to be idempotent from day one.

No event for everything you'd want. Flag the specific gaps — things you'd expect to have a webhook that don't. If organization events aren't firing yet given the beta status, that's worth noting. Any others from your experience.

Payload size and structure can change without notice. You've seen this firsthand — fields appear, fields disappear, fields are always null. Don't treat the payload as a stable contract. Always write defensive handlers that check for field existence before using a value.

Section 5 — Writing reliable webhook handlers (practical patterns)

This is where the article earns its keep for the developer who's read this far. Three or four patterns: Always validate the event type first

if (!payload.event) {
return res.status(400).json({ error: 'Missing event type' })
}

Check for field existence before using it

const ip = payload.user?.current_ip ?? null
// Don't assume it's there even if you've seen it before

Make handlers idempotent

Use a unique identifier from the payload (enrollment ID, sale ID) to check whether you've already processed this event before acting on it. Teachable can and will send duplicate events on retry. Log the raw payload before processing Always log what Teachable actually sent before you do anything with it. When something breaks three months from now you'll want to know exactly what came in. Include the full payload, timestamp, and event type at minimum.

Section 6 — The purple callout + CTA

Same pattern as the B2B article. The pivot paragraph:

None of this is insurmountable, but it does mean that a production-grade Teachable webhook integration requires more defensive coding than most platforms. The inconsistencies are manageable once you know about them — the danger is building on assumptions that seem reasonable until the edge case hits your live system at 2am.

Building this yourself vs. having it built

If you're a developer, this guide gives you what you need. If you're a school owner who's just realised this is more complex than expected — that's a completely reasonable conclusion. This is the kind of infrastructure Purple Hippo builds as a fixed-scope project.

Closing summary table

Webhook event Has IP data Consistent payload Notes
enrollment.created Mostly last_four always null
enrollment.completed Mostly last_four always null
sale.created Yes No IP — gap for fraud detection
comment.created Yes No IP
user.created TBC TBC Add from your experience
lesson.completed TBC TBC Add from your experience

One production note Same datestamp approach as the B2B article — this one especially since Teachable's webhook behaviour may change as they develop the v2 API. "Last verified: May 2026" at the top protects the content's credibility as the platform evolves.

Purple Hippo Web Studio

Need this built, not just documented?

We build custom Teachable integrations, webhook infrastructure, and B2B enrollment portals. Fixed scope, fixed price, no surprises.

Book a free discovery call