Skip to main content

Troubleshooting: Webinar registration and registrant lifecycle errors

A scheduled room’s register lives at /api/v1/video/rooms-scheduled/:id/registration (the form config) and /api/v1/video/rooms-scheduled/:id/registrants (the roster). Every rejection on those endpoints, and every refusal the join gate raises at an unregistered arrival, is a deterministic 4xx: the same room state rejects the same way every time, so the response tells you exactly which setting or roster state to change. This page indexes the whole ladder. All register responses share one envelope:
error.code names the class, error.message names the cause, and meta.request_id is what support needs if you escalate.

Which side is failing?

Work the section that matches your call. If a 5xx such as VIDEO_REGISTRANT_CREATE_FAILED shows up instead, the write never ran; retry once, then escalate with the request_id.

Decision checklist

  1. Read the gate as it stands. GET /:id/registration returns config (enabled, require_approval, require_registration, capacity, custom_fields) beside the live roster and the attendance report. Trust that read over what the dashboard last showed you.
  2. Match the message. Each row below names the state that fired it.
  3. Apply the fix, then resend the same request once. These rejects are deterministic; if the same 4xx returns, the fix did not land.

Register-time rejects (POST /:id/registrants)

A register that succeeds past the approved-seat cap is not an error: the attendee lands with "status": "waitlisted" and joins only after a PATCH approve frees a seat.

Decision-time rejects (PATCH /:id/registrants/:registrantId)

decline, block, and waitlist never hit the cap. Only approve does, and only when it moves a non-approved registrant to approved.

Check-in rejects (POST /:id/registrants/:registrantId/check-in)

A repeat check-in on an already-attended registrant succeeds and keeps the original attended_at; the report counts one attendance.

The walk-in gate: 403 at join

When require_registration (or require_approval) is on, the join gate checks every arrival against the roster and refuses an unmatched joiner with:
Roster matches get their own refusal until they are approved and a seat is free: VIDEO_REGISTRATION_PENDING, VIDEO_REGISTRATION_DECLINED, VIDEO_REGISTRATION_BLOCKED, and VIDEO_REGISTRATION_CAPACITY. A plain room with no register never returns these codes; a failed join there is a join-token or invite refusal, covered in Video room lifecycle failures. The code alone therefore tells you which door the joiner hit. To see why the gate fired, read it back: GET /:id/registration returns config.require_registration, config.require_approval, and config.enabled exactly as the gate evaluates them. The gate arms only while the register is enabled, and closing the register ({"enabled": false}) returns unmatched joiners to open-guest behaviour.

Required questions that name the question

The register 400 ("Company" is required) quotes the question’s label, and the registrant card in the dashboard marks which questions are required. Answers you save on the card sync to the roster on save, so a registrant who signed up before you added a required question can be completed there. Deleting and re-registering them instead mints a new join_token and breaks the link they already hold.

What NOT to do

  • Do not re-POST on a duplicate-email 409. The roster keeps one row per email; the retry cannot win and never merges. PATCH the existing row.
  • Do not loop approve against a capacity 409. Every approve returns the same 409 until a seat frees. Change the state once (free a seat or raise the cap), then approve.
  • Do not retry check-in on a pending or waitlisted registrant. The 409 holds until a successful approve; retrying changes nothing.
  • Do not delete-and-re-register to edit a registrant. The new row mints a new join_token, invalidating the attendee’s existing link.

When to escalate

Escalate to support when a write still fails after the state named in the fix column is confirmed by a fresh GET /:id/registration. Include the room id, the registrant id (vreg_…) or attendee email, the exact error.code and error.message, and meta.request_id from the failing response.

See also