Server API
Overview
You can utilize all the backend features of SpellSync on your game server. Payments, authentication, player data storage, leaderboards, chats, daily rewards, achievements, and more.
Each method call with an API access key is counted as 1 request. This includes administrator methods. Requests directly from the admin panel are not counted.
We use the GraphQL language for processing requests. This way, you can fetch only the data that you truly need.
Convenient SDK generators for making GraphQL requests:
- JavaScript / TypeScript / NodeJS: GraphQL-Codegen
- Golang: genqlient
- C# / .NET: Strawberry Shake
- Java / Kotlin: Apollo Kotlin
- Python: GQL
- PHP (without generation): PHP GraphQL Client
API is available at
https://api.spellsync.com/gs/api/graphql
All methods, input and output type schemas are available in introspection. To view the schema or work in a sandbox, use the Chrome extension - Altair GraphQL Client.
Getting API Key
- Go to the Account Settings section.
- In the API Keys section, create a key.
- Select which projects this key applies to or select all.
- Choose which API methods can be accessed with this key or select all.
Request Setup
GraphQL operates over https
protocol.
Request method: POST
.
Response format / Content-Type: JSON
.
Authentication is required for the request. Authentication occurs through headers, details below.
Admin Request
You can use all methods intended for our admin panel. For example, get project statistics or interact with a player: ban, delete, edit data.
The list of methods is available in documentation, under the Docs button in Altair.
Admin methods do not contain the Player prefix (except for working with the player module):
- FetchChannel
- CreateChannel
- FetchOnlineStats
For authentication, you need to pass the X-API-Secret
header:
# Access Key
X-API-Secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Example of forming headers in JS:
const headers = {
'Content-Type': 'application/json',
'X-API-Secret': 'mykey',
};
Player Request
The list of methods is available in documentation, under the Docs button in Altair.
Player methods start with the prefix Player
or contain it after the verb:
- PlayerFetchAchievements
- PlayerFetchLeaderboard
- FetchPlayerProjectConfig
- SyncPlayer
- GetPlayer
There are 2 authentication options: by player ID or by platform authorization data.
By Player ID
You need to pass headers:
# Access Key
X-API-Secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Project Number
X-Project-ID: 4
# Player ID
X-Player-ID: 579134513
Example of forming headers in JS:
const headers = {
'Content-Type': 'application/json',
'X-API-Secret': 'mykey', // Do NOT use this on the game client, only on the server, keep it secure
'X-Project-ID': '4',
'X-Player-ID': '579134513',
};
By Player Authorization Data
Player authorization data is data provided by platforms: tokens, identifiers, signatures, and other payload. It always varies from platform to platform, you can get it directly from our SDK ready for sending.
This data helps to directly authenticate the player as they are authenticated on the platform.
You need to pass headers:
# Access Key
X-API-Secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Project Number
X-Project-ID: 4
# Player Authorization Data (ss.player._authInfo)
X-Player-Data: eyJzZWNyZXRDb2RlIjoiOXFwTnlna2gifQ==
# Platform Type making the request (ss.platform.type)
X-Platform: YANDEX
Header X-Player-Data
This is a JSON in base64 format containing player authentication data:
- Secret code
- ID on the platform
- Player authentication token on the platform
- Other authentication parameters
Parameters always differ from platform to platform, and you should obtain authentication data from the player in the SpellSync client SDK, ss.player._authInfo
.
When authenticating with platform data, you must specify the authorizing platform in the X-Platform
header. If the request is not tied to a platform, you can omit the header.
Example of forming headers using platform data, in JS:
const headers = {
'Content-Type': 'application/json',
'X-API-Secret': 'mykey', // Do NOT use this on the game client, only on the server, keep it secure
'X-Project-ID': '4',
'X-Platform': ss.platform.type,
'X-Player-Data': btoa(JSON.stringify(ss.player._authInfo)),
};
Working with the API
A request to the API consists of 3 parts:
- Passing authentication headers (above)
- Passing the request schema
- Passing request variables
More information on working with GraphQL: GraphQL Queries and Mutations.
Each request returns a union type: either a response or an error. The error comes in the message
property of type Problem
.
... on Problem {
message
}
Checking the result type is done by comparing the __typename
of the result:
query {
result: FetchPlayerProjectConfig {
__typename
... on Problem {
message
}
... on PlayerProjectConfig {
project {
names {
en
}
}
}
}
}
__typename
will be one of the following:
"Problem"
"PlayerProjectConfig"
Example query to fetch project config by a player
fragment translations on Translations {
en
fr
it
de
es
zh
pt
ko
ja
ru
tr
ar
id
hi
}
query {
result: FetchPlayerProjectConfig {
__typename
... on Problem {
message
}
... on PlayerProjectConfig {
isDev
isAllowedOrigin
config {
lang
avatarGenerator
avatarGeneratorTemplate
ymCounterId
gtagCounterId
showLoader
showReqCounter
orientation
showOrientationOverlay
targetOS
showUnsupportedOSOverlay
communityLinks {
...translations
}
}
project {
names {
...translations
}
descriptions {
...translations
}
icon(w: 256, h: 256, crop: false)
mainChatId
enableMainChat
achievements {
isLockedVisible
isLockedDescriptionVisible
enableUnlockToast
}
ads {
showCountdownOverlay
showRewardedFailedOverlay
}
}
platformConfig {
appId
gameLink
communityLinks {
...translations
}
banners {
type
enabled
bannerId
desktopBannerId
frequency
refreshInterval
maxWidth
maxHeight
maxWidthDimension
maxHeightDimension
desktopMaxWidth
desktopMaxHeight
desktopMaxWidthDimension
desktopMaxHeightDimension
fitCanvas
position
limits {
hour
day
session
}
useNative
}
}
playerFields {
names {
...translations
}
key
type
default
important
variants {
value
names {
...translations
}
}
}
serverTime
gameVariables {
key
values {
en
}
type
}
rewards {
id
iconSmall: icon(w: 48, h: 48, crop: false)
icon(w: 256, h: 256, crop: false)
tag
isAutoAccept
mutations {
type
key
action
value
}
names {
...translations
}
descriptions {
...translations
}
}
triggers {
id
tag
isAutoClaim
descriptions {
...translations
}
conditions {
type
key
operator
value
}
bonuses {
id
type
}
}
achievements {
id
iconSmall: icon(w: 48, h: 48, crop: false)
icon(w: 256, h: 256, crop: false)
tag
rare
progress
maxProgress
unlocked
lockedIcon(w: 256, h: 256, crop: false)
lockedIconSmall: lockedIcon(w: 48, h: 48, crop: false)
progressStep
isPublished
isLockedVisible
isLockedDescriptionVisible
names {
...translations
}
descriptions {
...translations
}
}
achievementsGroups {
id
tag
achievements
names {
...translations
}
descriptions {
...translations
}
}
products {
id
icon(w: 256, h: 256, crop: false)
iconSmall: icon(w: 48, h: 48, crop: false)
tag
price
isSubscription
period
trialPeriod
yandexId
names {
...translations
}
descriptions {
...translations
}
}
products {
id
icon(w: 256, h: 256, crop: false)
iconSmall: icon(w: 48, h: 48, crop: false)
tag
price
isSubscription
period
trialPeriod
yandexId
names {
...translations
}
descriptions {
...translations
}
}
schedulers {
id
tag
type
days
isRepeat
daysBonuses {
day
bonuses {
id
type
}
}
triggers {
id
tag
isAutoClaim
descriptions {
...translations
}
conditions {
type
key
operator
value
}
bonuses {
id
type
}
day
}
isAutoRegister
}
events {
id
tag
icon(w: 256, h: 256, crop: false)
iconSmall: icon(w: 48, h: 48, crop: false)
dateStart
dateEnd
isAutoJoin
triggers {
id
tag
isAutoClaim
descriptions {
...translations
}
conditions {
type
key
operator
value
}
bonuses {
id
type
}
}
names {
...translations
}
descriptions {
...translations
}
}
acl {
canUploadImages
canUploadFiles
canConnectOnline
canCollectStats
}
}
}
}
Example of fetching player progress
query ($input: GetPlayerInput!) {
result: GetPlayer(input: $input) {
__typename
... on Player {
state
stats {
playtimeAll
playtimeToday
activeDays
activeDaysConsecutive
}
achievementsList {
achievementId
createdAt
progress
unlocked
}
purchasesListV2 {
productId
payload
gift
subscribed
createdAt
expiredAt
}
rewards {
rewardId
countTotal
countAccepted
}
triggers {
triggerId
claimed
}
segments
leftSegments
newSegments
playerSchedulers {
schedulerId
daysClaimed
stats {
activeDays
activeDaysConsecutive
}
}
playerEvents {
eventId
stats {
activeDays
activeDaysConsecutive
}
}
experiments {
experiment
cohort
}
rewardsData {
activatedTriggersNow
claimedTriggersNow
claimedSchedulersDaysNow {
schedulerId
day
}
givenAchievements
givenRewards
givenProducts
}
sessionStart
}
... on Problem {
message
}
}
}
And its variables with the parameter "is this the first request for the session", this is needed for statistics and generating a unique token per session, can be omitted within the server context.
{
"input": {
"isFirstRequest": false
}
}
Full example of a player data retrieval query in JS
const GET_PLAYER_QUERY = `query ($input: GetPlayerInput!) {
result: GetPlayer(input: $input) {
__typename
... on Player {
id
state
stats {
playtimeToday
}
}
... on Problem {
message
}
}
}`;
const input = {
isFirstRequest: true,
};
// The response will come in the result variable, as named in the above query
// result: GetPlayer()
const result = await fetch('https://api.spellsync.com/gs/api/graphql', {
headers: {
'Content-Type': 'application/json',
'X-API-Secret': 'mykey',
'X-Project-ID': '4',
'X-Player-ID': '579134513',
},
body: JSON.stringify({
query: GET_PLAYER_QUERY,
variables: { input },
}),
})
.then((r) => r.json())
.then((r) => r.data.result);
if (result.__typename === 'Problem') {
// request failed
throw result.message;
}
const player = result;
console.log(player.state.score);
See also:
📄️ API Methods
All methods, input and output type schemas are available in the introspection. To view the schema or work in a sandbox, use the Chrome extension - Altair GraphQL Client.
📄️ Webhooks
Track SpellSync events via Webhooks.
Stay in Touch
Other documents of this chapter available Here. To get started, welcome to the Tutorials chapter.
SpellSync Community Telegram
: @spellsync.
For your suggestions e-mail
: [email protected]
We Wish you Success!