Skip to main content

Fetch Users Data

Fetches user information and flight history for multiple users in a single request.

Headers

x-api-key
string
required
Your airline’s API token
Content-Type
string
default:"application/json"
Must be application/json

Body Parameters

Accepts either format: Format 1: Object with userIds array
{
  "userIds": ["123456789", "987654321"]
}
Format 2: Array of user IDs
["123456789", "987654321"]
userIds
string[]
required
Array of ROBLOX user IDs to fetch data for

Response

data
array
Array of user data objects, one for each requested user ID

Example Request

curl -X POST https://api.skyteam.dev/users/fetchUsersData \
  -H "x-api-key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "userIds": ["123456789", "987654321"]
  }'

Example Response

{
  "data": [
    {
      "userId": "123456789",
      "user": {
        "userId": "123456789",
        "username": "pilot123",
        "displayName": "Captain John",
        "miles": 5000,
        "avatarUrl": "https://tr.rbxcdn.com/...",
        "createdAt": "2024-01-10T08:00:00.000Z",
        "updatedAt": "2024-03-15T10:30:00.000Z"
      },
      "flights": [
        {
          "id": "550e8400-e29b-41d4-a716-446655440000",
          "code": "ST123",
          "gameId": "1234567890",
          "aircraft": "Boeing 737-800",
          "airlineId": "skyteam",
          "brandId": "skyteam-main",
          "departure": "KJFK",
          "arrival": "KLAX",
          "miles": 500,
          "startTime": "2024-03-15T14:00:00.000Z",
          "startedAt": "2024-03-15T14:05:00.000Z",
          "endTime": "2024-03-15T16:30:00.000Z",
          "codeshareAirlineId": null,
          "discordEventLink": "https://discord.gg/event/123456"
        }
      ]
    },
    {
      "userId": "987654321",
      "user": null,
      "flights": []
    }
  ]
}

Error Response

Status: 400 Bad Request
{
  "error": "Provide a list of userIds in the request body"
}

Implementation Notes

  • Duplicate user IDs are automatically de-duplicated to reduce database queries
  • Results are returned in the same order as requested
  • Users that don’t exist return null for the user object with an empty flights array
  • All user IDs are trimmed and filtered to remove empty strings

Buy Product

Purchases a miles product for a user, deducting the miles cost from their account.

Headers

x-api-key
string
required
Your airline’s API token
Content-Type
string
default:"application/json"
Must be application/json

Path Parameters

id
string
required
The ROBLOX user ID of the user purchasing the product

Body Parameters

productId
string
required
The ID of the product to purchase

Response

ok
boolean
Always true on success
user
object
Updated user object with new miles balance
product
object
The purchased product object

Example Request

curl -X POST https://api.skyteam.dev/user/123456789/buyProduct \
  -H "x-api-key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "productId": "a1b2c3"
  }'

Example Response

{
  "ok": true,
  "user": {
    "userId": "123456789",
    "username": "pilot123",
    "displayName": "Captain John",
    "miles": 4500,
    "avatarUrl": "https://tr.rbxcdn.com/...",
    "createdAt": "2024-01-10T08:00:00.000Z",
    "updatedAt": "2024-03-15T10:30:00.000Z"
  },
  "product": {
    "productId": "a1b2c3",
    "airlineId": "skyteam",
    "name": "Priority Boarding",
    "description": "Board the aircraft before other passengers",
    "priceMiles": 500,
    "active": true,
    "createdAt": "2024-01-15T10:30:00.000Z"
  }
}

Error Responses

Missing Product ID Status: 400 Bad Request
{
  "error": "Missing productId in body"
}
User Not Found Status: 404 Not Found
{
  "error": "User not found"
}
Product Not Found Status: 404 Not Found
{
  "error": "Product not found"
}
Insufficient Miles Status: 400 Bad Request
{
  "error": "Insufficient miles"
}

Transaction Behavior

  • The purchase is atomic - either both the miles deduction and transaction record succeed, or neither happens
  • A miles transaction record is created with type spend and source purchase
  • Only active products can be purchased
  • The product must belong to the authenticated airline

Implementation

Location: apps/api/src/routes/users.ts:74
router.post("/user/:id/buyProduct", async (req, res, next) => {
  const { id: userId } = req.params;
  const { productId } = req.body as { productId?: string };
  
  const airline = res.locals.airline as { airlineId: string };
  const [user, products] = await Promise.all([
    fetchUser(userId),
    fetchMilesProducts(airline.airlineId),
  ]);
  
  if (!user) return res.status(404).json({ error: "User not found" });
  
  const product = products.find(
    (p) => p.productId === productId && p.active !== false,
  );
  if (!product) return res.status(404).json({ error: "Product not found" });
  
  const updated = await spendMiles(
    userId,
    product.priceMiles,
    `Purchase: ${product.name}`,
  );
  
  res.json({ ok: true, user: updated, product });
});

Build docs developers (and LLMs) love