---
title: "Game SDK: покажете какво играят играчите в mssgs"
description: "Публикувайте от играта си статус „Playing“ с бутон Join now и проверявайте членството в общността. mssgs Game SDK за нативни, браузърни и мобилни игри."
canonical: https://docs.mss.gs/bg/game-sdk
language: bg
---

# Покажете какво играе някой

Позволете на играта си да казва на mssgs какво прави играчът. Приятелите му виждат „Playing“ под името му, отварят подробностите и с бутона Join now влизат в същата игра. Играта ви може също да провери дали играчът е във вашата общност.

## Какво можете да направите

- **Публикувайте статус на играта** Играта, какво прави играчът, ролята му и колко е пълна групата.

- **Добавете бутон Join now** Приятелите влизат в същата игра, сървър или лоби с едно натискане.

- **Проверявайте членството** Попитайте дали играчът е във вашата общност и с какви роли.

- **Компютър, браузър или телефон** Нативните игри използват локалния мост; игрите в браузъра и на телефона минават през вашия бекенд.

В приложението

Статусът под името и подробностите, които отваря. Играта е публикувала един JSON блок; останалото е работа на приложението.

- [Общ преглед](#overview)

- [Откриване на клиента](#discover)

- [Искане на разрешение](#authorize)

- [Статус на играта](#activity)

- [Join now](#join)

- [Браузър и телефон](#linked)

- [Справочник](#reference)

## Общ преглед

Настолното приложение на mssgs стартира малък **локален HTTP мост**, с който говори игра на същия компютър. Играта ви никога не говори с нашите сървъри, никога не вижда парола или токен на акаунта и никога не може да публикува от името на играча. Тя говори с копието на mssgs, в което играчът вече е влязъл, и това копие решава какво да отговори.

Какво можете да правите с него:

- Да разберете, че mssgs е инсталиран и някой е влязъл.

- Да прочетете кой е играчът: user_guid, username, аватар.

- Да попитате „този играч в общност X ли е?“ и каква роля има там.

- Да публикувате статус „Playing …“ с бутон **Join now** за останалите.

- Да получите данните за присъединяване, когато някой натисне този бутон.

### Два пътя

**Нативна игра за компютър** говори с локалния мост; това описват следващите раздели. Игра **в браузъра или на телефона** не може да достигне до този мост. За такива игри публикува вашият собствен бекенд, за играчите, които са свързали акаунта си в mssgs чрез QR код или код от осем знака: вижте [Игри в браузъра и на телефона](#linked), с [CozyCity](https://cozycity.net) като първи пример. Самият статус на играта е един и същ блок и в двата случая.

### Минимално разкриване по подразбиране

Обхватите умишлено не са равностойни. Ако ви трябва само „този човек в нашата общност ли е“, поискайте membership.query и сами посочете server_guid: получавате да/не плюс ролите му там и не научавате нищо за останалите му общности. Пълният списък стои зад отделен, по-висок обхват, който играчът трябва да одобри отделно.

## Откриване на клиента

Мостът слуша само на 127.0.0.1 , на първия свободен порт от малък диапазон. Опитвайте ги поред, докато някой отговори: **7440, 7441, 7442, 7443**. Версиите за разработка на mssgs слушат вместо това на **7540–7543**, така че тестова версия никога не отговаря на заявките на истинска игра.

Не е нужен токен, а отговорът не казва нищо за играча, само че mssgs е тук и дали някой е влязъл.

```json
{
  "product": "mssgs",
  "api": 1,
  "client": "desktop",
  "version": "14.2.20015",
  "platform": "darwin",
  "signed_in": true,
  "scopes": ["identity", "staff", "membership.query", "servers.list", "presence.write"]
}
```

Проверете product === "mssgs" и api , преди да продължите. Ако нито един от четирите порта не отговаря, mssgs не работи. Тогава просто предложете обичайното изживяване, вместо да карате играча да чака.

## Искане на разрешение

Всичко освен /hello изисква токен, а токен има едва след като играчът одобри играта ви в диалогов прозорец в приложението. Искайте само обхватите, които наистина използвате: играчът вижда всеки от тях поотделно, с обяснение, и може да махне отметката от всеки.

```bash
curl -X POST http://127.0.0.1:7440/mssgs/v1/authorize \
  -H "Content-Type: application/json" \
  -d '{
    "game_id": "com.acme.spacegame",
    "name": "Space Raiders",
    "scopes": ["identity", "membership.query", "presence.write"]
  }'
```

Получавате обратно {"status":"pending","request_id":"…","poll_after_ms":1000} , а играчът вижда диалоговия прозорец. След това проверявайте периодично, докато отговори (заявката изтича след 3 минути):

```bash
curl http://127.0.0.1:7440/mssgs/v1/authorize/<request_id>

# {"status":"approved","token":"…","scopes":["identity","presence.write"],"game_id":"com.acme.spacegame"}
```

### Винаги проверявайте какво точно сте получили

Списъкът scopes в отговора може да е **по-кратък** от поискания: играчът може да махне отметката от отделни обхвати. В примера по-горе membership.query е отказан. Разклонявайте логиката според това, което казва отговорът, а не според това, което сте поискали, иначе ще срещнете 403 MISSING_SCOPE , който не сте предвидили.

Запазете токена и го изпращайте като Authorization: Bearer <token> . Той оцелява след рестарт, така че играчът одобрява играта ви веднъж, а не при всяка сесия. Ако по-късно поискате оторизация отново с обхвати, които вече са дадени, получавате същия токен веднага, без диалогов прозорец.

## Обхвати и поверителност

Петте обхвата разкриват много различно количество данни. Това не е случайно, а е целият замисъл. Искайте възможно най-малко, като вървите отгоре надолу по таблицата.

| Обхват | Какво позволява | Какво дава играчът |
| --- | --- | --- |
| presence.write | **Показване какво играе** | Нищо. Този обхват само записва; не чете никакви данни от акаунта. |
| identity | **Кой е играчът** | user_guid, username, показвано име, URL на аватара. |
| staff | **Флагове за служител / модератор** | Две булеви стойности, в допълнение към identity. Отделно, защото игра, която показва име, няма работа да знае, че играчът модерира общности. |
| membership.query | **Проверка на общност, която вече знаете** | За server_guid, който посочите: да/не, името ѝ и ролите на играча там. Нищо за която и да е друга общност. |
| servers.list | **Всички общности, в които е** | Пълният списък: guid стойности, имена, икони и роли. Това е скъпият обхват: искайте го само ако наистина ви трябва. |

### На повечето игри им трябват два

identity и presence.write покриват „кой сте“ и „покажете какво играете“, тоест почти всяка интеграция. Добавете membership.query , ако искате да обвържете награда с членство във вашата общност. servers.list почти никога не ви трябва, а играчът го вижда маркиран в червено.

## Проверка на членство

Това е алтернативата на „дайте ми целия списък“. Посочвате server_guid на собствената си общност (който вече знаете) и получавате отговор само за нея.

```bash
curl -H "Authorization: Bearer $TOKEN" \
  "http://127.0.0.1:7440/mssgs/v1/membership?server_guid=ca94ecc…f4g02"

# член:
# {"server_guid":"ca94ecc…","member":true,"name":"Acme Fans","is_owner":false,
#  "roles":[{"guid":"0aa32…","name":"Pro"}]}

# не е член и нищо повече:
# {"server_guid":"…","member":false}
```

„Не“ означава точно това и нищо повече. В една заявка можете да подадете до 10 guid стойности (повторете server_guid или ги разделете със запетаи), което връща масив results . Групата @everyone никога не е в roles : тя важи за всеки член, така че не ви казва нищо.

## Публикуване на статус на играта

Една PUT заявка поставя реда „Playing …“ под името на играча навсякъде, където го виждат неговите общности.

```json
{
  "name":    "Space Raiders",
  "details": "Sector 7",
  "state":   "In a raid",
  "role":    "Gunner",
  "started_at": 1755859200000,
  "party":   { "size": 3, "max": 4, "kind": "party" },
  "join":    { "secret": "raid-42" }
}
```

Задължително е само name . Отговорът ви казва колко дълго живее статусът и колко често да изпращате heartbeat:

```json
{ "ok": true, "expires_in_ms": 90000, "heartbeat_every_ms": 30000 }
```

### Heartbeat, иначе статусът изчезва

Статус без признаци на живот в продължение на 90 секунди се изчиства автоматично. Това е умишлено: ако играта ви се срине, играчът не остава „в игра“ с часове. Изпращайте POST /mssgs/v1/activity/heartbeat на всеки 30 секунди и DELETE /mssgs/v1/activity при нормално затваряне.

### Брой играчи и роля

party.kind определя кое изречение се показва, защото едни и същи две числа не означават едно и също. Отряд от четирима не е сървър с четирима играчи.

| kind | Показва се като | За |
| --- | --- | --- |
| party (по подразбиране) | 3 of 4 in the party | отряд, екипаж или група |
| server | 4/100 players | сървър на игра (FiveM, сървър на общност) |
| lobby | 4/100 players | лоби преди началото на мача |
| match | 4/100 players | мач или рунд в ход |

role (до 48 знака) казва *като какъв* играе играчът: професия, клас или персонаж. Има собствено поле, а не още едно изречение в state , защото се показва като етикет до броя играчи.

details и state са ограничени до 128 знака всяко, name до 64. Преходите на нов ред и управляващите знаци се премахват. **URL адрес на икона умишлено не се поддържа**: той би се изтеглял от всеки клиент, който показва реда, а това превръща статуса в маяк, който докладва на вашия сървър всеки член на всяка общност, в която е играчът.

## Бутонът Join now

Сложете блок join в активността си и другите членове ще получат бутон **Join now** до статуса. Има два начина и можете да ги комбинирате.

### 1. Тайна стойност (за нативни игри)

Задайте {"join":{"secret":"raid-42"}} . Когато някой натисне Join now, тази тайна стойност се доставя до *неговото собствено* копие на вашата игра, на неговия собствен компютър, съпоставено по същия game_id . Не се отваря URL и не се извиква обработчик на схема. Играта ви я получава така:

```json
{
  "events": [
    { "seq": 1, "type": "join", "secret": "raid-42",
      "from": { "user_guid": "62e377…", "username": "mssgs-test-1" } }
  ],
  "cursor": 1
}
```

Проверявайте с ?since=<cursor> , за да виждате всяко събитие само веднъж. Ако играта на човека, натиснал бутона, не работи, нищо не се доставя, а това е добра причина да предложите и URL.

### 2. https URL (за уеб игри и линкове към лоби)

Задайте {"join":{"url":"https://play.example.com/s/abc"}} и бутонът ще отвори този линк. **Приема се само https .** Собствена схема ( steam:// , mygame:// , file:// ) се отказва: този блок се появява на екрана на всеки член, а такъв URL е начин да накарате чужд компютър да извика локален обработчик с аргументи, избрани от вас.

### Всичко в join е публично

Блокът join се разпраща до всеки, който може да види статуса на играча; точно в това е смисълът на бутона Join now. Затова го третирайте като код за лоби, а не като идентификационни данни. Никога не слагайте в него нищо, което трябва да остане тайно, и задавайте срок на валидност на кодовете си.

## FiveM

FiveM няма HTTP в клиентската си Lua среда, затова ресурсът говори с моста през **NUI**, CEF изглед, който изпраща Origin. Мостът изрично приема тези origin стойности: https://cfx-nui-<resource> и по-старото nui://<resource> . Обикновените уеб страници остават отказани, а страница в отворения уеб не може да си присвои този origin; браузърът го задава сам.

```lua
-- NUI страницата прави HTTP заявката; Lua само ѝ подава данните.
CreateThread(function()
  while true do
    SendNUIMessage({
      action  = 'mssgs:publish',
      players = GetActivePlayers and #GetActivePlayers() or 0,
      maxPlayers = GetConvarInt('sv_maxclients', 100),
      job     = exports['qb-core'] and 'Police' or nil
    })
    Wait(30000) -- heartbeat: статусът изтича след 90 с
  end
end)
```

```javascript
const BASE = 'http://127.0.0.1:7440/mssgs/v1';   // опитайте 7440-7443
let token = null;

async function authorize () {
  const res = await fetch(`${BASE}/authorize`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      game_id: 'fivem.lossantos.rp',
      name: 'Los Santos Roleplay',
      scopes: ['presence.write']          // тук не е нужно нищо повече
    })
  });
  const started = await res.json();
  if (started.status === 'approved') { return started.token; }

  // Сега играчът вижда диалога за разрешение в mssgs.
  for (let i = 0; i < 180; i += 1) {
    await new Promise((r) => { setTimeout(r, 1000); });
    const poll = await (await fetch(`${BASE}/authorize/${started.request_id}`)).json();
    if (poll.status === 'approved') { return poll.token; }
    if (poll.status !== 'pending') { return null; }
  }
  return null;
}

window.addEventListener('message', async (event) => {
  if (event.data.action !== 'mssgs:publish') { return; }
  if (!token) { token = await authorize(); }
  if (!token) { return; }

  await fetch(`${BASE}/activity`, {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` },
    body: JSON.stringify({
      name: 'FiveM',
      details: 'Los Santos Roleplay',
      role: event.data.job,                       // "Police"
      party: { size: event.data.players, max: event.data.maxPlayers, kind: 'server' },
      join: { url: 'https://cfx.re/join/abc123' } // вашият линк в cfx.re
    })
  });
});
```

Резултатът: **Playing FiveM · Los Santos Roleplay · 4/100 players · Police**, с бутон Join now, който отваря вашия линк в cfx.re.

### Искайте само presence.write

Статусът на играта не изисква нищо друго: този обхват не чете абсолютно нищо. Ако искате да обвържете награда в играта с членство във вашата общност в mssgs, добавете membership.query и посочете собствения си server_guid; пак не научавате нищо за другите общности на играча.

### Сървър, на който играете, не е автоматично доверен

Всеки FiveM сървър може да изпълнява клиентски ресурси, така че всеки сървър, в който някой влезе, може да поиска разрешение. Точно затова по средата стои диалогов прозорец, който назовава ресурса: решава играчът, не сървърът.

## Игри в браузъра и на телефона: свързване през вашия бекенд

Игра в раздел на браузъра или на телефон не може да достигне до моста по-горе. Той работи на компютъра на играча, а по пътя стоят три стени: мостът отказва всяка заявка с браузърен Origin ; Chrome показва запитване за разрешение, преди публична страница да изпрати заявка до 127.0.0.1 , а Safari направо отказва; телефонът пък изобщо няма път до loopback адреса на компютъра.

Затова посоката се обръща. **Вашият собствен бекенд вече знае кой играе и той казва на mssgs**, за играчите, които са свързали акаунта си в mssgs с вашата игра. Връзката се одобрява *в приложението mssgs*, никога във вашата игра, и създава връзка, никога сесия: нищо по-долу не може да впише някого или да действа от името на играча. Клиентът на играта ви никога не вижда ключ и никога не говори с mss.gs. Първата игра по този път е [CozyCity](https://cozycity.net), градостроителна игра, която се предлага като WebGL страница и приложение за iPhone, без версия за компютър; примерите по-долу са нейните.

### 1. Регистрирайте играта си

Регистрирайте играта на [страницата за регистрация в Game SDK](https://mss.gs/bg/docs/game-sdk/register): вашия game_id (например com.deverence.cozycity ), името и иконата, които играчът вижда в прозореца за одобрение, и имената на хостовете на вашия бекенд. Преглеждаме я там и след одобрение вашият **ключ за бекенда** ви чака на същата страница, показан само веднъж; ние пазим само хеш от него. Ключът трябва да стои на вашия сървър и никъде другаде. Можете да го смените там по всяко време, а старият остава валиден 24 часа, за да може новото внедряване да мине спокойно.

[Регистрирайте играта си](https://mss.gs/bg/docs/game-sdk/register)

Името и иконата в прозореца **винаги идват от регистрацията**, никога от заявката. Иначе фишинг линк би могъл да представи заявка за свързване като която и да е игра. Имената на хостовете ограничават къде може да сочи join.url , вижте по-долу.

### 2. Свържете играч

Играчът избира **Connect mssgs** във вашата игра. Играта пита вашия бекенд, а бекендът пита нас:

```bash
curl -X POST https://ams1-gateway.mss.gs/game-sdk/v1/link/start \
  -H "Authorization: Bearer $BACKEND_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "player_ref": "player-8812", "player_name": "René\u2019s city" }'

# {"link_code":"K7PQ2XM4","device_code":"…","qr_url":"https://mss.gs/gl/K7PQ2XM4",
#  "deep_link":"mssgs://link-game/K7PQ2XM4","expires_in":600,"interval":5}
```

player_ref е вашият собствен постоянен идентификатор за този играч (до 128 знака), а не за сесия или мач; player_name (до 64) е това, което прозорецът показва като „Player: …“. Дайте на клиента на играта само link_code , qr_url и deep_link . device_code ви служи за периодичната проверка и остава на сървъра.

След това играта ви показва три неща едновременно, защото играчът може да е навсякъде:

- **QR кода** на qr_url . Телефон с mssgs го отваря направо в прозореца за одобрение в приложението. Без приложението се стига до страница в mss.gs, която показва кода и предлага изтегляне.

- **Бутон „Open in mssgs“** с deep_link , за браузър на компютър, на който работи и настолното приложение. Това е единственият външен URL, който играта ви някога трябва да отвори.

- **Самия код**, в две групи по четири знака, за въвеждане в **Settings → Game Activity → Link a game**. В азбуката няма 0/O и 1/I, така че при въвеждане рядко се допуска грешка.

Какво вижда играчът в mssgs, в прозорец, който приложението изгражда от регистрацията:

### Connect CozyCity to your mssgs account?

CozyCity will be able to show what you are playing as your mssgs status. It will not see your messages, your friends or your servers, and it cannot post as you. Player: *René's city* · **Connect** / **Not now**

Междувременно вашият бекенд проверява на всеки interval секунди (на по-чести заявки отговорът е 429 SLOW_DOWN ), докато статусът се промени. Кодът работи веднъж и изтича след десет минути:

```bash
curl -X POST https://ams1-gateway.mss.gs/game-sdk/v1/link/poll \
  -H "Authorization: Bearer $BACKEND_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "device_code": "…" }'

# {"status":"pending"}
# {"status":"denied"}      # играчът избра Not now
# {"status":"expired"}
# {"status":"linked","link_guid":"…","user":{"user_guid":"62e377…"}}
```

Запазете link_guid към вашия играч; отсега нататък това е адресът, за който публикувате. Отговорът съдържа само user_guid ; username се добавя само когато регистрацията ви има обхвата identity.link , и нищо повече. Второ одобрение за същия player_ref **заменя** предишната връзка, така че един играч на вашата игра е един акаунт в mssgs. Един и същ акаунт в mssgs може да е свързан с няколко игри и с няколко player_ref на една игра (семеен iPad).

### 3. Публикувайте статуса на играта

Същият блок като при [моста](#activity), със същите правила и същите ограничения, само че сега за всяка връзка поотделно и с вашия ключ за бекенда:

```json
{
  "activity": {
    "name":       "CozyCity",
    "details":    "Lantern Hollow",
    "state":      "Day 12 · 34 residents",
    "started_at": 1788901000000,
    "party":      { "size": 6, "max": 40, "kind": "server" },
    "join":       { "url": "https://cozycity.net/game/?share=…" }
  }
}
```

```bash
200 {"published":true,"changed":true}     # блокът се промени и беше разпратен
200 {"published":true,"changed":false}    # идентичен със запазения; обновен е само TTL
204                                        # запазен, но играчът в момента не е онлайн в mssgs
410 {"error":"LINK_REVOKED"}               # играчът прекъсна връзката: премахнете я
```

Третирайте 200 и 204 еднакво: запазено. { "activity": null } изчиства блока, изпратете го, когато играчът излезе. Една разлика спрямо моста: хостът на join.url трябва да е един от регистрираните ви бекенди (или негов поддомейн), иначе получавате 400 INVALID_PAYLOAD . Така бекендът не може да сложи в статуса на играча бутон Join now, който води някъде, където този играч никога не е играл.

### Heartbeat на всеки 60 секунди, TTL 120

Публикуваният статус живее **120 секунди** без ново съобщение и после изчезва сам. Затова изпращайте същия блок отново на всеки 60 секунди; непроменен блок не струва нищо и само обновява TTL. Ако heartbeat спре, спира и редът „Playing …“, и точно това е целта.

При стотици играчи онлайн изпращайте heartbeat с една заявка, до 100 елемента наведнъж. Всеки елемент получава собствен статус, така че един играч, прекъснал връзката в mssgs, никога не спира останалите деветдесет и девет:

```json
{ "items": [ { "link_guid": "…", "activity": { "name": "CozyCity", "details": "Lantern Hollow" } },
             { "link_guid": "…", "activity": null } ] }

// → 200 { "results": [ { "link_guid": "…", "status": 200, "changed": false },
//                      { "link_guid": "…", "status": 410 } ] }
```

### Как се показва статусът

- Също като статус от моста: **Playing CozyCity · Lantern Hollow · 6/40 players**, с Join now, когато има join.url . Сървърът маркира блока с via: "backend" , така че клиентът може да добави „Shared by the game's server“.

- **Само докато играчът е онлайн в mssgs.** Без отворен клиент на mssgs акаунтът е офлайн и остава офлайн; вашият бекенд не може да накара някого да изглежда на линия. Това също пречи на този път да се превърне в маяк „дали René е на компютъра си“.

- Приоритет: **игра в приложението > игра през моста > вашият бекенд**. Ако играчът седне да играе шах в mssgs, докато бекендът ви продължава да изпраща heartbeat, печели шахът, а не този, който е писал последен.

### Прекъсване на връзката

Играчът вижда всяка връзка в **Settings → Game Activity → Linked games**, с вашата икона и име, името на играча от вашата игра, кога е свързана и кога е публикувала за последно, и бутон **Disconnect**. След това следващата ви публикация получава отговор 410 LINK_REVOKED ; така играта ви разбира. Премахнете link_guid и отново предложете „Connect mssgs“. От ваша страна прекратявате връзка с DELETE /game-sdk/v1/links/{link_guid} .

### Ограничения

За всяка връзка *промяна* се отчита най-много веднъж на 2 секунди; непроменен heartbeat е безплатен. За всеки ключ има 600 заявки в минута, като елементите в пакетна заявка се броят поотделно: heartbeat за 300 играчи на всеки 60 секунди изразходва 5 от 600-те.

## Справочник за крайните точки: мостът

Базов URL http://127.0.0.1:<port> . Всичко освен първите три изисква Authorization: Bearer <token> .

| Метод | Път | Scope | Какво прави |
| --- | --- | --- | --- |
| GET | /mssgs/v1/hello | няма | Тук ли е mssgs, каква версия на API поддържа и дали някой е влязъл. Единственият маршрут, който не изисква токен, и не казва нищо за играча. |
| POST | /mssgs/v1/authorize | няма | Поискайте разрешение от играча. Отваря диалогов прозорец в приложението и връща request_id за периодична проверка. |
| GET | /mssgs/v1/authorize/:request_id | няма | pending, approved (с токена), denied или expired. |
| GET | /mssgs/v1/me | identity | Влезлият играч. Добавя is_staff / is_moderator само с обхвата staff. |
| GET | /mssgs/v1/membership | membership.query | Членство в подадените стойности на server_guid (до 10, повторени или разделени със запетаи). |
| GET | /mssgs/v1/servers | servers.list | Всички общности, в които е играчът, с ролите му. Личните съобщения никога не се включват. |
| PUT | /mssgs/v1/activity | presence.write | Публикувайте блока „Playing …“. Връща TTL и колко често да изпращате heartbeat. |
| POST | /mssgs/v1/activity/heartbeat | presence.write | Поддържайте публикуваната активност жива, без да я изпращате отново. |
| DELETE | /mssgs/v1/activity | presence.write | Изчистете я веднага, при нормално затваряне. |
| GET | /mssgs/v1/events | presence.write | Данни за присъединяване, насочени към вашата игра. Проверявайте с ?since=<cursor>. |
| GET | /mssgs/v1/session | няма | Какво съдържа този токен: game_id, дадените обхвати, дали някой е влязъл. |
| DELETE | /mssgs/v1/session | няма | Върнете разрешението. Същият ефект, както когато играчът го отмени в Settings. |

## Справочник за крайните точки: свързани бекенди

Базов URL https://ams1-gateway.mss.gs . Всеки маршрут изисква Authorization: Bearer <backend key> и обхвата activity.write в регистрацията ви; отговорите излизат с Cache-Control: no-store . Извиквайте ги от сървъра си, никога от клиента на играта.

| Метод | Път | Какво прави |
| --- | --- | --- |
| POST | /game-sdk/v1/link/start | Започнете свързване за един от вашите играчи ({ player_ref, player_name? }). Връща link_code, device_code, qr_url, deep_link, expires_in и interval. |
| POST | /game-sdk/v1/link/poll | { device_code } → pending, denied, expired или linked с link_guid и user. |
| DELETE | /game-sdk/v1/links/{link_guid} | Прекратете връзка от ваша страна. Играчът може да направи същото от Settings. |
| PUT | /game-sdk/v1/links/{link_guid}/activity | Публикувайте блока „Playing …“ за един играч; { "activity": null } го изчиства. |
| POST | /game-sdk/v1/activity/batch | Същото, за до 100 играчи в една заявка. Всеки елемент получава собствен отговор. |

## Кодове за грешки

Грешките се връщат като {"error":"CODE","message":"…"} със съответния HTTP статус.

| Код | Значение |
| --- | --- |
| 401 UNAUTHORIZED | Липсващ или непознат токен; първо поискайте оторизация. |
| 403 MISSING_SCOPE | Играчът не е дал това разрешение. Може да е махнал отметката. |
| 403 ORIGIN_NOT_ALLOWED | Заявката съдържа браузърен Origin. Вижте „Само нативни игри“ по-долу. |
| 409 NOT_SIGNED_IN | mssgs работи, но никой не е влязъл. |
| 429 RATE_LIMITED | Повече от 120 заявки в минута от една игра. |
| 400 INVALID_GAME_ID | game_id може да съдържа само букви, цифри, точка, тире или долна черта. |
| 400 TOO_MANY_GUIDS | Най-много 10 стойности на server_guid в една заявка за членство. |

### Свързани бекенди

Маршрутите за бекенда използват същия формат. В пакетна заявка статусът се връща за всеки елемент поотделно в results , така че една прекратена връзка никога не проваля цялата заявка.

| Код | Значение |
| --- | --- |
| 401 INVALID_BACKEND_KEY | Непознат ключ или ключ, сменен преди повече от 24 часа. |
| 403 SCOPE_NOT_GRANTED | Регистрацията ви няма обхвата, който изисква този маршрут. |
| 400 INVALID_PAYLOAD | Невалидно тяло на заявката, повече от 100 елемента в пакет или join.url, чийто хост не е от регистрираните ви бекенди. |
| 400 INVALID_ACTIVITY | След нормализирането не е останало използваемо име. |
| 410 LINK_REVOKED | Връзката е прекратена, от едната или от другата страна. Премахнете я и отново предложете „Connect mssgs“. |
| 429 SLOW_DOWN | Проверявали сте link/poll по-често от interval. |
| 429 RATE_LIMITED | Промяна на една връзка до 2 секунди след предишната или повече от 600 заявки в минута с вашия ключ. |
| 503 LINK_STORE_UNAVAILABLE | Временен проблем от наша страна. Опитайте отново при следващия heartbeat. |

## Сигурност

### Само нативни игри

Заявки с Origin на уеб страница се отказват с 403 ORIGIN_NOT_ALLOWED . Ако всяка уеб страница можеше да разбере, че използвате mssgs, и да отвори диалог за разрешение, това би било вратичка за fingerprinting и фишинг, а не функция. Нативната игра изобщо не изпраща Origin, така че това не я засяга, а вграденият браузър на игра е разрешен поименно, вижте [FiveM](#fivem). Ако създавате игра за браузър или телефон, вие не говорите с моста: вашият собствен бекенд публикува за свързаните играчи, вижте [Игри в браузъра и на телефона](#linked).

### Какво остава под контрола на играча

- Играчът може да изключи моста в **Settings → Game Activity**, след което никоя игра изобщо не вижда mssgs.

- Всяка одобрена игра е изброена там точно с разрешенията, които има, кога е била активна за последно и бутон **Remove**. Премахването е незабавно: токенът спира да действа веднага.

- Свързана игра в браузъра или на телефона е изброена в **Linked games** с бутон **Disconnect**. Прекъсването също е незабавно: следващата публикация на този бекенд получава 410 .

- Мостът слуша само на 127.0.0.1, никога в мрежата.

- Личните съобщения никога не се разкриват, дори със servers.list.

- Всяка игра има лимит от 120 заявки в минута.

### Добри практики

- Искайте обхвати, когато ви трябват, а не всички наведнъж при първото стартиране.

- Работете и без mssgs: играчът не е длъжен да го има.

- Изчиствайте статуса си, когато играта спре, вместо да чакате TTL.

- Третирайте отказан обхват като нормален резултат, а не като грешка.

## Продължете нататък
