GoHighLevel workflows and inbox
This connector is available through Beta access while we prepare the public Marketplace release. Request Beta access to receive your setup link.
Connect a HighLevel sub-account to a Miss Blue project for direct messaging, or use project API keys and webhooks to build your own workflow integration.
Connect the Miss Blue app
The Marketplace integration is available through Beta access. An owner or admin can check availability under Project → Integrations → GoHighLevel. It requires an active dedicated Miss Blue number; shared testing numbers cannot be connected to a GHL inbox.
Request Beta access to receive an installation link for your GHL location. The connector is not yet generally available in the public Marketplace. Use a dedicated sub-account for initial setup. Developers can refer to the HighLevel private-app installation guide for the version-specific installation process.
Starting in GHL? After installing the app, create a Miss Blue account or sign in. Your new account includes a workspace and project automatically. Your dashboard shows Finish setting up GoHighLevel, with a link to plans and number setup. Once your number is active, use that card to approve the GHL connection. You can also resume setup here.
Already using Miss Blue? Open your project's Integrations page and follow these steps:
- Choose the initial sending number. After connecting, Project Settings lets you keep a specific default or enable Auto round robin across the project’s numbers. Each number has its own 50-new-contact rolling daily allowance; replies keep the contact’s saved number. For an agency installation, also enter the GHL sub-account ID from Settings → Business Profile.
- Choose Connect Beta location, approve contacts and conversations access, and return in the same browser and Miss Blue sign-in.
- After the conversation provider is configured, select the Miss Blue channel in GHL Conversations. New direct messages sync both ways. Existing history and group conversations are not imported.
Contact matching stays inside the connected sub-account. Delivery and read statuses update when Miss Blue receives confirmation. Hidden senders and messages hidden from members are excluded. View connection health and recent synchronization under the project's Integrations page.
Send text and media separately. The current send path accepts one file or a set of images; mixed file types in a single send are unsupported. Files copied into the GHL inbox must meet GHL's limit of five files, each no larger than 5 MB. Larger files remain accessible in Miss Blue.
The additional Miss Blue channel does not replace your existing SMS provider. Workflows use a Custom Webhook action calling the Miss Blue API below; the standard GHL SMS action does not select this channel. FaceTime Audio and regular phone calls run in Miss Blue, not the GHL native dialer.
Duplicate deliveries of the same GHL message ID are deduplicated. If an inbox import loses its confirmation, it is shown as Confirmation missing and is not automatically posted again. Check the GHL conversation and contact support before retrying. Disconnecting cancels GHL messages still waiting to send; it cannot recall a message already dispatched.
Build your own integration
- An active Miss Blue project and sending number, plus a project API key from API keys.
- Your project ID, number ID from
GET /v1/numbers, and an HTTPS webhook receiver with durable storage and a job queue. - Access to the GHL sub-account you want to connect. Inbox support additionally needs your own Marketplace Conversation Provider app and OAuth installation.
Keep the Miss Blue key on your backend and use Authorization: Bearer …. A key sees only its project. A key labelled mb_test_ can still send real messages.
The Miss Blue calls
| Purpose | Endpoint |
|---|---|
| Choose a sending line | GET /v1/numbers |
| Send text or a reply | POST /v1/messages |
| Upload an outgoing file | POST /v1/attachments |
| Read authoritative message state | GET /v1/messages/{id} |
| Reconcile conversation history | GET /v1/messages?number_id=…&chat_id=… |
| Download received media | GET /v1/messages/{id}/attachments/{attachment_id} |
| Register signed events | POST /v1/projects/{id}/webhooks |
| Inspect webhook delivery attempts | GET /v1/projects/{id}/webhooks/{endpoint_id}/deliveries |
Send from a workflow
For an outbound workflow, GHL's Custom Webhook action can call https://api.missblue.dev/v1/messages directly: choose POST, bearer authentication with your project key, and JSON using the fields below. Insert the contact phone using GHL's field picker. Inbox synchronization requires the project's GHL connection above or your own integration backend. Read the retry limitations below before enabling automatic retries.
Use a HighLevel Custom Webhook action to call your backend. Map the contact phone, message, location, and a unique execution reference. The backend selects the saved project key and number; it must not trust a number ID supplied by an unrelated location.
curl -X POST https://api.missblue.dev/v1/messages \
-H "Authorization: Bearer $MISS_BLUE_KEY" \
-H "Content-Type: application/json" \
-d '{
"number_id": "8f14e45f-ceea-467a-9a1b-1b1e5f9e2c3d",
"recipient": "+15555550100",
"text": "Your appointment is confirmed."
}'Save the returned Miss Blue id against the GHL message or execution. Accepted or queued work is not a delivery receipt. For an existing thread, include its exact chat_id. Treat it as opaque and URL-encode it in query parameters.
Build your own GHL inbox provider
Create an OAuth Marketplace app targeting sub-accounts, initially private for testing. Your backend hosts the redirect URL, exchanges the code, stores and refreshes tokens, and binds the returned location to the chosen Miss Blue project. A GHL Private Integration Token alone does not configure a conversation channel.
For an additional Miss Blue channel, configure an SMS Conversation Provider, check Is this a Custom Conversation Provider, and save its provider ID. Use the alias Miss Blue. This preserves the existing SMS provider. GHL uses SMS as the provider category; Miss Blue still sends through its messaging infrastructure.
Typical scopes are conversations/message.readonly, conversations/message.write, conversations.readonly, conversations.write, contacts.readonly, and contacts.write; request only those your implementation uses. The additional channel needs a custom workflow action or your Custom Webhook workflow; the standard SMS action does not select it.
- GHL → Miss Blue: your provider Delivery URL receives
locationId,contactId,messageId,phone,message, and attachments. VerifyX-GHL-Signatureagainst the raw body using Ed25519 before dispatching. Provider deliveries do not include the legacy RSA header. Provider contract. - Miss Blue → GHL: match the saved location, number, thread, and sender handle. Use POST /conversations/messages/inbound with
type: SMS, yourconversationProviderId, a contact or conversation ID, and the received message. Store the GHL message ID it returns. - Delivery: map Miss Blue delivery and failure events to PUT /conversations/messages/:messageId/status using the same provider app's OAuth token. Keep unconfirmed sends pending; do not translate
message.sentinto delivered.
Do not feed generic GHL outbound notifications back into sending: mirrored messages can otherwise loop. Keep each contact mapping scoped to its location and each Miss Blue thread scoped to its number. Calls, group-chat parity, and typing indicators in the GHL inbox need separate integration work.
Receive signed replies and outcomes
curl -X POST https://api.missblue.dev/v1/projects/$PROJECT_ID/webhooks \
-H "Authorization: Bearer $MISS_BLUE_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-backend.example/hooks/missblue",
"events": ["message.received", "message.sent", "message.delivered", "message.failed"]
}'Store the returned signing secret. Verify Miss-Blue-Signature: t is Unix seconds and v1 is the hex HMAC-SHA256 of t + "." + rawBody, keyed by the exact secret string. Use constant-time comparison and a bounded timestamp tolerance, such as five minutes. Persist the event before returning 2xx, then process it asynchronously.
The envelope is { id, type, created, data }. Message fields are under data.message, alongside data.number and data.project_id. For incoming messages, api_id names the Miss Blue API row and sender_handle is the resolved contact phone or email. Legacy id and from remain platform identifiers. Nullable enrichment fields mean the integration must reconcile rather than guess.
Deduplicate delivery retries by envelope id. Multiple platform observations can concern the same incoming message; use api_id to update its existing GHL mapping. Do not create a second inbox item when attachment metadata is enriched. Events marked is_action, is_hidden, or is_deleted must not be inserted as ordinary new messages.
Attachments
For outbound media, download the GHL file on your backend with URL, type, size, and redirect checks, then upload its raw bytes to Miss Blue. Pass the returned ID in attachment_ids; arbitrary file URLs are not accepted by the send endpoint. Text and files require separate sends. Multiple attachments in one send must all be images.
Incoming webhook attachments include metadata and IDs. Download each file through the message-scoped endpoint above with your project key, then upload or securely host it for GHL. GHL cannot fetch a Miss Blue URL that requires your bearer key. Never put that key in a URL. A 404 can mean the file is unavailable or access is denied; reconcile message metadata and retry missing uploads only within a bounded policy.
Retries and recovery
The send API currently has no client-supplied idempotency key. Deduplicate GHL executions in your own database before sending, and retain the returned Miss Blue ID. A timeout or 504 leaves the outcome uncertain: read the message or reconcile the transcript before deciding on another send. Do not blindly retry or use allow_duplicate as a retry mechanism.
Webhook deliveries retry with backoff, but are not an exactly-once stream. Poll GET /v1/messages with number, direction, since/until, limit, and offset filters to repair missed incoming events; reread outstanding outgoing IDs for status changes. Overlap polling windows and deduplicate by API ID. Honor 429 and Retry-After. Read receipts can be polled through message state; there is no message.read webhook.
Before enabling customer traffic, test one location and a contact you control: text both ways, media both ways, delayed receipts, repeated events, expired OAuth tokens, revoked project keys, wrong-location requests, and an ambiguous send timeout. The integration owner must verify the actual GHL app installation end to end.
NextWebhook payload and delivery detailsThe exact Miss Blue event shape and polling paths.