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 for token lifecycle and security details.
1. Request integration credentials
Ask your Eyemagnet account manager, or email 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, andmodify 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.