Inbox
Embed a full-featured messaging inbox into your application
The inbox embed gives your users a complete RCS and SMS messaging experience — conversations, message history, rich media, and real-time updates.

Step 1: Backend
Create an endpoint that requests a signed JWT from Pinnacle. Control which conversations and UI appear in the inbox.
import 'dotenv/config';
import express from 'express';
const app = express();
app.use(express.json());
app.post('/api/get-inbox-token', async (req, res) => {
const response = await fetch('https://api.pinnacle.sh/embed/get-token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'pinnacle-api-key': process.env.PINNACLE_API_KEY!
},
body: JSON.stringify({
inboxFilter: {}, // optional — pass brandIds or senders to filter, or {} for a team-level inbox
scopes: [
'CONVERSATIONS.LIST', // required
'CONVERSATIONS.MESSAGES', // required
'CONVERSATIONS.SEND',
'CONVERSATIONS.CREATE',
'UPLOAD_FILE',
'REALTIME.CONNECTION'
]
})
});
const { signedToken } = await response.json();
res.json({ signedToken });
});
app.listen(8080, () => {
console.log('Server running at http://localhost:8080');
});Schema
| Field | Type | Required | Description |
|---|---|---|---|
inboxFilter | object | Yes | Filter conversations by brandIds or senders, or pass {} for a team-level inbox |
scopes | string[] | Yes | Permissions granted to the token |
Set inboxFilter to control which conversations appear in the inbox.
| Field | Type | Description |
|---|---|---|
brandIds | string[] | Show conversations for the specified brand IDs. |
senders | string[] | Show conversations for specific RCS agent IDs or phone numbers in E.164 format (e.g. +14155550123). |
Choose one filter
Use brandIds or senders, not both. For all team conversations, use inboxFilter: {}.
Step 2: Frontend
Add the iframe to your page. Subscribe to the message event to listen for INBOX_READY, then send INIT_INBOX with your signed token to initialize the inbox.
<!-- Other page content -->
<iframe
id="inbox"
src="https://embed.pinnacle.sh/embed/v2/inbox"
style="width: 100%; height: 100vh; border: none;">
</iframe>
<!-- Other page content -->
<script>
const iframe = document.getElementById('inbox');
window.addEventListener('message', async (event) => {
if (event.origin !== 'https://embed.pinnacle.sh') return;
if (event.data.type === 'INBOX_READY') {
// Fetch token from your backend
const res = await fetch('/api/get-inbox-token', { method: 'POST' });
const { signedToken } = await res.json();
// Initialize the inbox
iframe.contentWindow.postMessage({
type: 'INIT_INBOX', // required
signedToken: signedToken, // required
primaryColor: '#16a34a'
}, 'https://embed.pinnacle.sh');
}
if (event.data.type === 'INBOX_ERROR') {
// handle iframe init failure here
}
});
</script>
<!-- Other page content -->Events
| Field | Type | Description |
|---|---|---|
INIT_INBOX | postMessage | Send signed token and configuration to initialize the inbox |
INBOX_READY | event | Iframe has loaded and is ready to receive configuration |
INBOX_ERROR | event | Validation or initialization error occurred |
| Field | Type | Required | Description |
|---|---|---|---|
type | "INIT_INBOX" | Yes | Message type identifier |
signedToken | string | Yes | JWT token from your backend |
primaryColor | string | No | Primary color for the inbox (defaults to #16a34a) |
Complete Integration
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Inbox</title>
</head>
<body>
<iframe
id="inbox"
src="https://embed.pinnacle.sh/embed/v2/inbox"
style="width: 100%; height: 100vh; border: none;">
</iframe>
<script>
const iframe = document.getElementById('inbox');
window.addEventListener('message', async (event) => {
if (event.origin !== 'https://embed.pinnacle.sh') return;
if (event.data.type === 'INBOX_READY') {
// Fetch token from your backend
const res = await fetch('/api/get-inbox-token', { method: 'POST' });
const { signedToken } = await res.json();
// Initialize the inbox
iframe.contentWindow.postMessage({
type: 'INIT_INBOX', // required
signedToken: signedToken, // required
primaryColor: '#16a34a'
}, 'https://embed.pinnacle.sh');
}
if (event.data.type === 'INBOX_ERROR') {
// handle iframe init failure here
}
});
</script>
</body>
</html>