> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getmelody.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Publication Flow

> Connect a publisher application to the Haptics server over WebSocket and transmit haptic signals.

This is a step-by-step guide to connecting a **publisher** application to the Haptics server and transmitting signals. It assumes your device is already linked to a Melody account.

***

## 1. Obtain an authentication token

Request a short-lived authentication token and server endpoint from the **App Publisher Auth** endpoint (see the [API Reference](/api-reference)).

```bash theme={null}
curl -X POST -H 'Content-Type: application/json' \
  https://api.getmelody.io/api/haptics/auth/publisher/app
```

The response contains the WebSocket endpoint and a token to connect with:

```json theme={null}
{
  "ws_endpoint": "wss://ws.endpoint/haptics",
  "ws_proxy_endpoint": "wss://ws.endpoint/haptics",
  "token": "eyJ0eX..."
}
```

<Note>`ws_proxy_endpoint` is deprecated — use `ws_endpoint`.</Note>

***

## 2. Connect and authenticate

Connect to the Haptics server over WebSocket and send a [HapticFrame](/melody/streaming/haptic_frames) carrying a Protobuf `Auth` message.

**Open the connection:**

```go theme={null}
dialer := websocket.Dialer{
	TLSClientConfig: &tls.Config{},
}

conn, _, err := dialer.Dial("wss://ws.endpoint/haptics", nil)
```

**Send the authentication frame:**

```go theme={null}
authProto := &entities.Auth{
	JwtToken: token, // token from step 1
}

bytes, err := proto.Marshal(authProto)

authFrame := &protocol.HapticFrame{
	Type: entities.FrameType_SUBSCRIPTION,
	Data: bytes,
}

err = authFrame.WriteFrame(c.stream)
```

***

## 3. Handle TimeSync

Echo `TIME_SYNC` frames back so clients can control the quality of the stream, and react to `CONNECTION_INFO` events.

```go theme={null}
for {
	dataFrame, err := protocol.ReadNextFrame(c.stream)

	switch dataFrame.Type {
	// Echo the system TIME_SYNC event back
	case entities.FrameType_TIME_SYNC:
		dataFrame.WriteFrame(c.stream)

	// Adjust internal algorithms using connection info
	case entities.FrameType_CONNECTION_INFO:
		// TODO: your logic

	default:
	}
}
```

***

## 4. Submit signals

Build a `HapticSignal` from one or more `DeviceCommand`s, marshal it, wrap it in a `SIGNAL` frame, and write it to the stream.

```go theme={null}
command := &entities.DeviceCommand{
	Time:    1234567890, // milliseconds
	Channel: 1,
	Pos:     1234, // [0..10000)
}

signalProto := &entities.HapticSignal{
	Commands: []*entities.DeviceCommand{command},
}

bytes, err := proto.Marshal(signalProto)

signalFrame := &protocol.HapticFrame{
	Type: entities.FrameType_SIGNAL,
	Data: bytes,
}

err = signalFrame.WriteFrame(c.stream)
```

This connects a publisher to the Haptics server, authenticates it, and transmits signals to subscribers. To receive signals instead, see the [Subscription Flow](/melody/streaming/subscription).
