---
title: Eyemagnet API common usage
description: "Step by step guide to the Eyemagnet API server to server flow: request integration credentials, mint a bearer token, read a player and its channels, and send a channel change trigger."
---

[Skip to content](https://support.eyemagnet.com/eyemagnet-api-common-usage#main-content)

English

Show submenu for translations

[Customer portal](https://support.eyemagnet.com/tickets?hsLang=en)

![Logos-1](https://support.eyemagnet.com/hubfs/Logos/Logos-1.svg)

- [Knowledge Base Home](https://support.eyemagnet.com/)

Open main navigation

Close main navigation

- [Knowledge Base Home](https://support.eyemagnet.com/)
- English
  
  Show submenu for translations
- [Customer portal](https://support.eyemagnet.com/tickets)
- [eyemagnet.com](https://www.eyemagnet.com/)

[eyemagnet.com](https://www.eyemagnet.com/)

 Hi, how can we help you?

- There are no suggestions because the search field is empty.

1. [Eyemagnet Knowledge Base](https://support.eyemagnet.com/?hsLang=en)
2. [Developer Portal](https://support.eyemagnet.com/developer-portal?hsLang=en)
3. [Getting Started](https://support.eyemagnet.com/developer-portal?hsLang=en#getting-started)

# Eyemagnet API common usage

## Step by step guide to the Eyemagnet API server to server flow: request integration credentials, mint a bearer token, read a player and its channels, and send a channel change trigger.

This walkthrough shows the usual server-to-server flow: obtaining integration credentials, minting a bearer token, reading a player and its channels from Media API v1, then sending that player a channel-change trigger through Media API v2.

Keep all credentials and tokens in a trusted backend. Do not include them in a browser application, mobile app, or published source code.

**Creating a token:** This guide uses the Auth v2 `keyAuthentication` flow. See the **[Auth v2 integration guide](https://support.eyemagnet.com/auth-api-integration-guide?hsLang=en)** for token lifecycle and security details.

---

### **1. Request integration credentials**

Ask your Eyemagnet account manager, or email [support@eyemagnet.com](mailto:support@eyemagnet.com), for an integration with access to the intended team.

Provide the team, player, and intended use case. Request the following values:

| Value | Why it is needed |
| --- | --- |
| Auth v2 base URL | Mint the bearer token. |
| Media API v1 base URL | Read the player and its available channels. |
| Media API v2 base URL | Publish the channel-change trigger. |
| Client ID and client secret | Identifies your server-side integration. |
| Key ID and key secret | Identifies the machine/service principal. |
| Team ID | Selects the media tenant. |
| Scopes | `query players`, `query channels`, and `modify players`. |

The key must belong to, or be permitted to act in, the supplied team. Use a dedicated key for each deployment and rotate it if it is exposed.

---

### **2. Mint a bearer token**

Call Auth v2 from your backend. Limit the token to the three scopes required by this workflow and request token version `v2`.

```
const authBaseUrl = "https://auth.example.com/auth/v2";const response = await fetch(authBaseUrl, {  method: "POST",  headers: { "Content-Type": "application/json" },  body: JSON.stringify({    query: `      mutation KeyAuthentication(        $client: ClientLogin!        $key: KeyLogin!        $team: Reference        $limits: [String!]      ) {        keyAuthentication(          client: $client          key: $key          team: $team          limits: $limits        ) {          bearerToken(version: "v2")          refreshToken(version: "v2")        }      }    `,    variables: {      client: { id: "<client-id>", secret: "<client-secret>" },      key: { id: "<key-id>", secret: "<key-secret>" },      team: { id: "<team-id>" },      limits: ["query players", "query channels", "modify players"],    },  }),});const { data, errors } = await response.json();if ( !response.ok || errors?.length ) {  throw new Error( errors?.[ 0 ]?.message || "Token request failed" );}const { bearerToken: accessToken, refreshToken } = data.keyAuthentication;
```

Store `accessToken` and `refreshToken` only in encrypted server-side storage. The bearer token is used in the next two steps. A successful response does not mean its requested scopes were granted; make sure the provisioned key has the three requested scopes.

---

### **3. Read the player and its channels from Media API v1**

Use the player ID supplied by Eyemagnet or recorded by your integration. The player’s `channel` is its current channel; `onDemandChannels` contains its other assigned channels. Choose a returned channel ID before publishing a channel trigger.

```
const mediaV1BaseUrl = "https://media.example.com/media/v1";const playerId = "<player-id>";const response = await fetch(mediaV1BaseUrl, {  method: "POST",  headers: {    "Content-Type": "application/json",    "Authorization": `Bearer ${accessToken}`,  },  body: JSON.stringify({    query: `      query PlayerChannels($id: ID!) {        player(id: $id) {          id          name          channel { id name }          onDemandChannels { id name }        }      }    `,    variables: { id: playerId },  }),});const { data, errors } = await response.json();if ( !response.ok || errors?.length || !data?.player ) {  throw new Error( errors?.[ 0 ]?.message || "Player was not found" );}const player = data.player;const channels = [ player.channel, ...player.onDemandChannels ].filter(Boolean);
```

For example, select one of the returned channel IDs:

```
const targetChannelId = channels[0].id; 
```

---

### **4. Send the channel-change trigger through Media API v2**

Publish a `CHANNEL` trigger to the same player. `ids` restricts the command to that player; `value` is the chosen channel ID from step 3. The token’s active team must be the same team that owns the player.

```
const mediaV2BaseUrl = "https://media.example.com/media/v2";const response = await fetch(mediaV2BaseUrl, {  method: "POST",  headers: {    "Content-Type": "application/json",    "Authorization": `Bearer ${accessToken}`,  },  body: JSON.stringify({    query: `      mutation ChangePlayerChannel(        $ids: [ID!]        $type: TriggerType!        $value: ID      ) {        trigger(ids: $ids, type: $type, value: $value)      }    `,    variables: {      ids: [player.id],      type: "CHANNEL",      value: targetChannelId,    },  }),});const { data, errors } = await response.json();if ( !response.ok || errors?.length || data?.trigger !== true ) {  throw new Error( errors?.[ 0 ]?.message || "Channel trigger was not published" );}
```

`trigger: true` confirms that Media API v2 published the event. It does not confirm that the player was online, received the event, or completed the channel change. Do not automatically retry the request unless your integration can safely tolerate a duplicate command.

---

### **Checklist**

- Keep client and key secrets server-side and out of logs.
- Mint v2 bearer tokens and send them only over HTTPS.
- Request only `query players`, `query channels`, and `modify players`.
- Use a channel ID returned for the player; do not assume channel IDs across teams are interchangeable.
- Send `ids: [player.id]` so a channel change cannot target every player in the team.

[![Logos](https://support.eyemagnet.com/hubfs/Logos/Logos.svg "Logos")](https://www.eyemagnet.com/)

©2026 Eyemagnet Limited. All Rights Reserved.

<https://www.linkedin.com/company/eyemagnet>