SOT Ship Invite API — Documentation
A minimal REST API to create Sea of Thieves captain's ships sessions.
Sea of Thieves
API
Guild
Quickstart
- Get an API key from the admin and keep it secret.
- Send the
X-Api-Keyheader with every request. - Call POST /api/invitations with
shipIdandgamertag. - Follow progress with SSE events or poll the status endpoint.
Base URL
Production
https://sotguildapi.live
Authentication
Every request must include:
X-Api-Key: <your_base64_key>
Missing or invalid keys return 401/403.
Errors
Errors are structured like:
{
"detail": { "code": "invalid_api_key", "message": "X-Api-Key missing or invalid" }
}
| HTTP | Meaning |
|---|---|
| 400 | Bad request (missing/invalid JSON or headers) |
| 401/403 | Missing/invalid API key |
| 404 | Not found (e.g., shipId absent from DB) |
| 502 | Upstream Xbox error or expired token not recoverable |
| 500 | Internal server error |
GET /health
Simple heartbeat to confirm the API is running.
Request
curl -s https://sotguildapi.live/health
200 Response
{"status":"ok"}
POST /api/invitations
Starts a SOT session + Xbox crew session and sends an invitation to the provided gamertag.
Body (JSON)
{
"shipId": "<shipID>", // UUID
"gamertag": "<gamertag>" // ex: 2584878536129841
}
Headers
Content-Type: application/json
X-Api-Key: <base64_key>
Example (curl)
curl -X POST https://sotguildapi.live/api/invitations \
-H 'Content-Type: application/json' \
-H 'X-Api-Key: YOUR_CLIENT_KEY' \
-d '{"shipId":"<shipID>","gamertag":"<gamertag>"}'
202 Response (example)
{
"task_id": "<taskId>",
"status_url": "/api/invitations/<taskId>",
"events_url": "/api/invitations/<taskId>/events"
}
If shipId is not found in DB, the API returns 404. Xbox 403 triggers a token refresh; if refresh fails, 502 is returned.
GET /api/invitations/{taskId}
Check the current state of an invitation task (use it if you prefer polling instead of SSE).
Request
curl -s -H 'X-Api-Key: YOUR_CLIENT_KEY' \
https://sotguildapi.live/api/invitations/<taskId>
200 Response (examples)
{
"taskId": "...",
"state": "pending", // pending | running | succeeded | failed | cancelled
"progress": 35, // 0..100 (optional)
"lastEvent": "session.created",
"updatedAt": "2025-09-02T12:34:56Z"
}
{
"taskId": "...",
"state": "succeeded",
"invited": { "gamertag": "<gamertag>", "xuid": "..." }
}
{
"taskId": "...",
"state": "failed",
"error": { "code": "xbox_token_expired", "message": "Token could not be refreshed" }
}
GET /api/invitations/{taskId}/events
Server-Sent Events stream to follow real-time progress.
Request
curl -N \
-H 'Accept: text/event-stream' \
-H 'X-Api-Key: YOUR_CLIENT_KEY' \
https://sotguildapi.live/api/invitations/<taskId>/events
Events (examples)
event: session.created
data: {"sessionId":"...","type":"SmallShip"}
event: invite.sent
data: {"to":"<gamertag>","xuid":"..."}
event: member.joined
data: {"gamertag":"<gamertag>"}
event: error
data: {"message":"Xbox token expired","retry":true}
Examples
Python (requests)
import requests
API="https://sotguildapi.live/api/invitations"
headers={"X-Api-Key":"YOUR_CLIENT_KEY","Content-Type":"application/json"}
body={"shipId":"<shipID>","gamertag":"<gamertag>"}
r=requests.post(API,json=body,headers=headers,timeout=30)
print(r.status_code, r.text)
Node.js (fetch)
const res = await fetch('https://sotguildapi.live/api/invitations', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.API_KEY
},
body: JSON.stringify({ shipId: 'f07b...', gamertag: '<gamertag>' })
});
console.log(res.status, await res.text());
Notifications
- SSE via
/api/invitations/{taskId}/events - Polling via
/api/invitations/{taskId}