Receive events over a long connection
Start with the recommended long connection. Your server opens it; no public receiver URL, challenge, HMAC Secret, Verification Token or Encrypt Key is needed. Use the application's service identity and Client Credentials. User login credentials cannot receive this connection.
This is a runnable Node.js 22 example with no dependencies, not an SDK. You can also use HTTPS Webhooks with an existing public receiver. Synchronous callbacks continue to use HTTPS separately.
Diagram: choose long connection or HTTPS for asynchronous events; configure synchronous callbacks separately. This illustrates a flow rather than a Console screenshot.
1. Select events
Open the current application → Events and webhooks and keep the recommended long connection. If no service identity is available, select “Enable application identity” on this event page and wait for the platform to confirm the current state before continuing. Enabling identity does not grant business API permissions. Add at least one event and save. No events can be received with zero selections or an inactive configuration. This page does not open a connection for your server.
2. Configure and run the example
Download event-connection.mjs and copy the event page's “application settings” into a server-side .env. The template includes the exact Application ID, environment and service OAuth Client ID. Supply the current environment's API Base and that Client's Secret. Supply Identity Issuer too if unavailable. Never use a user identity Client or credentials from another application or environment.
GOODVISION_API_BASE=<GOODVISION_API_BASE>
GOODVISION_IDENTITY_ISSUER=<GOODVISION_IDENTITY_ISSUER>
GOODVISION_APPLICATION_ID=<CURRENT_APPLICATION_ID>
GOODVISION_APPLICATION_ENVIRONMENT=sandbox
GOODVISION_SERVICE_CLIENT_ID=<CURRENT_SERVICE_CLIENT_ID>
GOODVISION_SERVICE_CLIENT_SECRET=<CURRENT_SERVICE_CLIENT_SECRET>Protect .env; keep it out of source control and browsers. Run:
node --env-file=.env event-connection.mjsThe example reads the Token Endpoint from the exact Issuer's Discovery document and obtains a client_credentials Bearer with openplatform.api.invoke. Tokens stay in memory and the Authorization header, never URLs, Inbox files or logs. Current application authorization and source restrictions apply to both connection and ACK requests. The example does not bypass them.
Original events are saved in event-inbox/ and sample results in event-inbox/results/. Set GOODVISION_EVENT_INBOX for another persistent directory. Use a separate directory per application and environment, with one receiver process. Preserve the files for restart recovery; this is not a disposable cache.
3. Send a test and integrate your business handler
Send a selected event from Sandbox Event testing and check the example's status and Delivery logs. connected only means the connection opened. delivery_processed means sample processing and the ACK succeeded. Queue acceptance does not prove receipt.
The example's separate onEvent callback only persists sample results; it does not activate services, pay or change permissions. Replace it with your business handler. Validate customer, resource and environment against the current event schema, process idempotently using event_id within your business transaction, and return only after success. Keep synthetic Sandbox events separate from real business processing.
Inbox persists received, calls onEvent, then persists processed after success and finally ACKs. A received event runs again. A repeated processed event only acknowledges its new current lease without repeating the handler. A crash between committing a business effect and writing processed can repeat the handler, so business work still needs idempotency. This does not guarantee exactly-once business effects.
Connection and recovery contract
| Item | Behavior |
|---|---|
| Connect | GET /open-platform/v1/applications/{id}/events:stream; SSE frames are connected, delivery, heartbeat and error |
| Delivery | Includes subscription_id, delivery_id, event_id, lease_receipt, lease_expires_at and complete event |
| Acknowledge | POST /open-platform/v1/applications/{id}/events:ack; Body contains only delivery_id and lease_receipt |
| Lease | 30 seconds; one unacknowledged delivery per subscription; expired, duplicate or old-generation ACKs return 409 |
| Disconnect / 503 | Reconnect with exponential backoff; unacknowledged events can be redelivered; Last-Event-ID is not an ACK |
| Lost ACK response | Do not force ACK with an old receipt; use actual redelivery and its current lease; processed prevents repeated callbacks |
| 401 / 403 | Stop; check the current service identity, Secret, Scope, application status and source restrictions, then run again |
| Processing failure | Do not write processed or ACK; resume after fixing the handler |
{"delivery_id":"delivery_opaque","lease_receipt":"receipt_opaque"}Successful responses have schema_version: "1", the original delivery_id and status: "delivered". Never persist lease receipts or print Token responses, raw network errors or event bodies in ordinary logs. See the event catalog for fields.