---
title: "App Messages"
canonical_url: https://developer.repebble.com/guides/alloy/app-messages/
last_updated: 2026-02-19
sdk_version: 4.33.1
---
# App Messages

Source: https://developer.repebble.com/guides/alloy/app-messages/

The Message API provides direct communication between watch code and PebbleKit JS (PKJS) on the phone. Unlike [networking](https://developer.repebble.com/guides/alloy/networking.md), app messages don't require the `@moddable/pebbleproxy` package - they use Pebble's built-in messaging system.

Code examples in this guide are labeled with **📱 PKJS** or **⌚ Watch** to indicate where they run.

## Watch-Phone Messaging

Use the `Message` class to send and receive structured data between the watch and PKJS:

**⌚ Watch** (src/embeddedjs/main.js):

```
import Message from "pebble/message";const message = new Message({keys: ["COMMAND", "DATA", "RESULT"],onReadable() {const msg = this.read();msg.forEach((value, key) =\> {console.log(key + ": " + value);});},onWritable() {console.log("Ready to send messages");},onSuspend() {console.log("Messages suspended");}});
```

The `keys` array lists the message key names used for communication. These must match the keys defined in `package.json`.

The `onWritable` callback fires when the `Message` instance is ready to send messages. The `onSuspend` callback is the opposite - it fires when sending is temporarily unavailable (e.g., the PKJS connection is lost or another `Message` instance is sending). A new `Message` instance begins in the suspended state.

## Sending Messages from Watch

**⌚ Watch** (src/embeddedjs/main.js):

```
message.write(new Map([["COMMAND", 1],["DATA", 42]]));
```

## Message Keys in package.json

Message keys must be defined in `package.json` as an array:

```
{"pebble": {"messageKeys": ["COMMAND","DATA","RESULT"]}}
```

## Receiving Messages in PKJS

**📱 PKJS** (src/pkjs/index.js):

```
Pebble.addEventListener('appmessage', function(e) {console.log("Received from watch: " + JSON.stringify(e.payload));// Send a response back to watchPebble.sendAppMessage({'RESULT': 123});});
```

## Combining with the Network Proxy

If your app uses both app messages and the network proxy, set up the PKJS to handle both:

**📱 PKJS** (src/pkjs/index.js):

```
const moddableProxy = require("@moddable/pebbleproxy");Pebble.addEventListener('ready', moddableProxy.readyReceived);Pebble.addEventListener('appmessage', function(e) {if (moddableProxy.appMessageReceived(e))return;// Handle your own app messages hereconsole.log("Received from watch: " + JSON.stringify(e.payload));});
```

The proxy's `appMessageReceived()` returns `true` if the message was for the proxy (e.g., a `fetch()` request). If it returns `false`, the message is one of your own and you can handle it.

## Getting GPS Location

For GPS location, use the `Location` sensor instead of app messages. See the [Sensors and Input](https://developer.repebble.com/guides/alloy/sensors-and-input.md) guide for details on the Location sensor, or the [watchface tutorial Part 4](https://developer.repebble.com/tutorials/alloy-watchface-tutorial/part4.md) for a complete weather example.

## Examples

The [Pebble Examples](https://github.com/Moddable-OpenSource/pebble-examples) repository includes app message examples:

- [`hellomessage`](https://github.com/Moddable-OpenSource/pebble-examples/tree/main/hellomessage) - sending and receiving messages between watch and phone
- [`helloconnected`](https://github.com/Moddable-OpenSource/pebble-examples/tree/main/helloconnected) - monitoring watch-phone connection status
