How your technology stack connects to Beluga's nationwide physician network. You own the patient experience end to end; Beluga handles clinical review, prescribing, and compliance behind a simple API. This guide walks through exactly what you build, what you send, and what you receive at each step.
Authorization: Bearer {API_KEY} on every requestapi-staging.belugahealth.comapi.belugahealth.comWhat this takes: this is an API integration, built by your developers. Plan for engineering resources on your side to build the intake, submit visits, and receive webhooks. If you don't have a dev team in-house, tell your onboarding contact up front — we'll help you scope the build (and Beluga can host the patient questionnaire as an add-on).
Meet your onboarding team (contracts, integration, forms & config), review the Partner Onboarding Guide, complete the Integration Form, receive the questionnaire documents, and book your kickoff call.
Receive your API & webhook docs, API credentials and environment details for both staging and production, and dashboard access. Integrate Beluga's patient consent and privacy policy into your intake, and review the available visit types.
Send a staging test visit from your fully built system (not Postman) using the sample visit type and MedID, including a photo to the receivePhotos endpoint. Share the masterId for review.
Share your webhook endpoint URLs, authentication details, and success/error responses. Beluga configures delivery and confirms each event type before moving on.
Enable live video: pass the scheduleLink to patients, then test BOOKING_CREATED / RESCHEDULED / CANCELLED (and NO_SHOW) in a sync-enabled state.
Turn on pharmacy fulfillment and test the order and tracking webhooks with a staging visit. (Refill triggering is enabled here too, where applicable.)
Enable lab orders for both in-person and at-home methods, and test the lab status webhooks with two staging visits.
Beluga builds the clinical questionnaires as the source of truth for your Q&A branching logic — used exactly as provided. The questionnaire documents are shared at kickoff, so this work runs in parallel from day one; this phase locks the final configuration before launch. Prefer not to build the intake UI yourself? Beluga can host the questionnaire as an add-on.
Your visit type goes live in production with your production API key. The milestone that matters: your first patient — a real visit through your own flow. From there your account manager and CS manager take over from onboarding and work with you on growing volume, adding programs, and switching on new capabilities.
In plain terms: build the questions and consent screen your patients fill out inside your product.
consentsSigned: true.patientPreference. Your Beluga customer dashboard is the source of truth for medIds: pull your program's catalog from there rather than hardcoding.Q1/A1 ... Qn/An. Embed multiple-choice options in the question text ("... POSSIBLE ANSWERS: a; b; c") and join multi-answers with semicolons.patientVerified: true and a verificationId with each visit.In plain terms: send the completed intake to Beluga; a licensed physician in the patient's state picks it up from there.
consentsSigned + demographics + patientPreference[] + the structured meds / allergies / conditions fields + your Q&A pairs.masterId (a unique ID you generate per visit), pharmacyId, company, visitType, plus patientVerified and verificationId if you verify identity.scheduleLink for booking — surface it as described in Step 4.200. The actual outcome lives in the response body (status, error, info fields), so parse the body rather than relying on the HTTP code. An HTTP 400 with an empty body means an authorization problem only: check your Bearer key and environment.In plain terms: send us any photos or documents the visit needs — an ID, a progress photo, a lab report.
mime to match the format: POST {visitId, images: [{mime, data}]}.{visitId, image: {mime: "application/pdf", data}}, one per request. Also the route for lab reports you hold as documents.visitId or the masterId from the visit response works as the key.200 means the request reached us; the body carries the result. HTTP 400 with no body is an authorization issue.In plain terms: in some states the patient books a live video call with the physician instead of chat-only care.
scheduleLink comes from the visit response: submit the visit (Step 2) first, and in live-video states the response includes the link.scheduleLink, query parameters included: they identify the visit.scheduleLink is used to both schedule and reschedule the live video consultation within that visit.BOOKING_CREATED with docName, scheduledDate (ISO 8601), location — here location is the live video consultation URL.BOOKING_RESCHEDULED (same fields), BOOKING_CANCELLED, NO_SHOW.In plain terms: the physician can message your patient with questions, and the patient replies through you.
{firstName, lastName, content, isMedia, masterId}. For images, send base64 as content with isMedia: true.{content, masterId}.DOCTOR_CHAT with content: display it to the patient in your chat UI — or deliver it by SMS if you don't have a chat UI.CS_MESSAGE with content: route it to your support team.In plain terms: the physician decides — prescription or referral — and you're notified the moment it happens.
{masterId}. Returns canceled, or resolved if the physician already acted.RX_WRITTEN: the prescription has been written. Payload details are in your webhook docs.CONSULT_CONCLUDED: fires on resolution with visitOutcome: "prescribed" | "referred". This is your signal the visit is complete.CONSULT_CANCELED: the patient canceled the consultation before a physician engaged.In plain terms: track the prescription or lab kit from order to the patient's door, event by event.
PHARMACY_ORDER_IN_FULFILLMENT → PHARMACY_ORDER_SHIPPED (with carrier, tracking) → PHARMACY_ORDER_DELIVERED.PACKAGE_IN_TRANSIT, PACKAGE_OUT_FOR_DELIVERY, PACKAGE_DELIVERED, PACKAGE_DELIVERY_FAILED with trackerStatus, trackerId, trackingUrl, tracking, carrier, deliveredDate.orderId + masterId tie every event back to the visit.LAB_ORDER_SHIPPED_TO_PATIENT (with carrier, tracking) → LAB_ORDER_DELIVERED_TO_PATIENT → LAB_ORDER_SHIPPED_TO_LAB → LAB_ORDER_RECEIVED_BY_LAB.LAB_ORDER_REQUISITION_CREATED delivers the requisition as a base64 PDF (labReqPdf) for the patient to bring to the draw site.LAB_ORDER_RESULTS (with bookingLink). Results also populate labResults[] on the GET visit endpoint. Running your own testing instead? Submit results through the lab-results endpoint in Step 2.RX_WRITTEN: no downstream tracking events are available for those orders.In plain terms: everything you can look up, update, or automate after a visit is underway.
GET /visit/externalFetch/{masterId}: visitStatus, resolvedStatus + timestamps, labResults[], the full formObj + intakeResults, rxHistory[], and AutoRx fields (currentDose, nextDose, checkinResult).GET /patient/externalFetch/{phone}: demographics plus every masterId on file for the patient.{name, city, state, zip} returns the first 100 matches.VISIT_DATA_UPDATED before the physician resolves, NEW_RX_SENT after. Window is 20 days from the original rx; retries are capped.NEW_RX_SENT. Windows: 15-60 days after a 1-month rx, 60-120 after a 3-month rx (staging compresses to 1 minute-4 days for testing).weightlossCheckin visit carries titration (Increase / Decrease / Stay the same), BMI (must exceed 20), and titrationLevel 1-3 for 3-month authorizations.{medId, masterId} returns NEW_RX_SENT + orderId; 14-day spacing; must match the original rx exactly.resolvedStatus moves open → closed, with resolvedTimestamp once closed.status, error, info). An HTTP 400 with an empty body signals an authorization problem only: check your Bearer key and environment.