OpenAPI spec drift in memory-store queue and sorted-map endpoints

The Open Cloud OpenAPI spec at Roblox/creator-docs/…/openapi.json disagrees with the live API at apis.roblox.com in 7 places across the memory-store queue and sorted-map endpoints. SDK generators that take the spec as ground truth (Stainless, openapi-generator with strict validation, oapi-codegen, etc.) produce clients whose requests are rejected or whose response parsers silently drop fields.

The 7 cases

# Endpoint Field Spec says Server wants
1 POST .../queues/{q}/items request data optional required (400 without)
2 POST .../queues/{q}/items request path mutable server-assigned, silently stripped
3 GET .../queues/{q}/items:read response wrapper { items, readId } { queueItems, id }
4 POST .../queues/{q}/items request ttl format: "duration" (PT5S) protobuf "5s"
5 GET .../queues/{q}/items:read query invisibilityWindow format: "duration" (PT3S) protobuf "3s"
6 GET .../sorted-maps/{m}/items response wrapper { memoryStoreSortedMapItems } { items }
7 POST .../sorted-maps/{m}/items request ttl format: "duration" (PT5S) protobuf "5s"

Steps to reproduce

Create an empty universe, mint an Open Cloud API key with read+write+delete on memory-store queue and sorted-map items, then make these requests against https://apis.roblox.com. Each block below is one drift.

#1 — queue create requires data:

POST .../queues/{q}/items  body: {"ttl":"5s"}
<<< 400 {"error":"INVALID_ARGUMENT","message":"The required field 'data' is missing."}

#2path is silently stripped:

POST .../queues/{q}/items  body: {"data":{"x":1},"path":"cloud/v2/universes/0/.../forged"}
<<< 200 {"path":"cloud/v2/universes/{REAL}/.../7fff...0002","data":{"x":1},...}

Tested 5 path variants (well-formed, mismatched universe, malformed string,
null, omitted) — all return 200; the server always emits its own path
keyed off the URL.

#3 — read response keys differ:

GET .../queues/{q}/items:read?count=10&invisibilityWindow=3s
<<< 200 {"queueItems":[...],"id":"b725dbafb1334e57b3db616c0b7713c6"}

DiscardMemoryStoreQueueItemsRequest correctly uses readId on the
request side; only the response schema is wrong.

#4 — queue ttl rejects ISO 8601:

POST .../queues/{q}/items  body: {"data":{"x":1},"ttl":"5s"}   <<< 200
POST .../queues/{q}/items  body: {"data":{"x":1},"ttl":"PT5S"} <<< 400 "The 'ttl' field is not correctly formatted."

#5invisibilityWindow rejects ISO 8601:

GET .../queues/{q}/items:read?invisibilityWindow=3s   <<< 200
GET .../queues/{q}/items:read?invisibilityWindow=PT3S <<< 400 "The 'invisibilityWindow' field is not correctly formatted."

#6 — sorted-map list response array key differs:

GET .../sorted-maps/{m}/items?maxPageSize=100
<<< 200 {"items":[...],"nextPageToken":null}

#7 — sorted-map ttl rejects ISO 8601:

POST .../sorted-maps/{m}/items  body: {"value":1,"ttl":"PT5S"}
<<< 400 "The 'ttl' field is not correctly formatted."

Aside (not a spec bug, server inconsistency)

MemoryStoreSortedMapItem.path comes back as memory-store/sorted-maps (singular) on create and list, but memory-stores/sorted-maps (plural) on get. Same item, two path shapes.

Direct links

Visual aids

None — this is an HTTP API drift; all evidence is textual and inline above.

System information

  • API endpoint: https://apis.roblox.com
  • Probe date: 2026-05-14
  • Probe runtime: Bun 1.3.13 on Windows 11, native fetch (no SDK)
  • Spec version probed against: upstream commit 3dedc83c559bc97392afc7d5add766e74994969f
  • Test universe: empty, throwaway
  • Auth: Open Cloud API key with universe.memory-store-{queue,sorted-map}-item:{read,write,delete} scopes

Suggested fix (diff against 3dedc83)

@@ Cloud_ReadMemoryStoreQueueItems > parameters > invisibilityWindow > schema
               "example": "3s",
-              "type": "string",
-              "format": "duration"
+              "type": "string"
@@ components > schemas > ListMemoryStoreSortedMapItemsResponse > properties
-          "memoryStoreSortedMapItems": {
+          "items": {
@@ components > schemas > MemoryStoreQueueItem > properties > path
             "type": "string",
-            "description": "The resource path of the memory store queue item.\n..."
+            "description": "The resource path of the memory store queue item.\n...",
+            "readOnly": true
@@ components > schemas > MemoryStoreQueueItem > properties > ttl
             "type": "string",
-            "description": "The TTL for the item.",
-            "format": "duration"
+            "description": "The TTL for the item."
@@ components > schemas > MemoryStoreQueueItem
         "x-oneOf": {
           "expiration": ["ttl", "expireTime"]
-        }
+        },
+        "required": ["data"]
@@ components > schemas > MemoryStoreSortedMapItem > properties > ttl
             "type": "string",
-            "description": "The TTL for the item.",
-            "format": "duration"
+            "description": "The TTL for the item."
@@ components > schemas > ReadMemoryStoreQueueItemsResponse > properties
-          "readId": {
+          "id": {
             "type": "string",
             "description": "An identifier of the read operation..."
           },
-          "items": {
+          "queueItems": {

Expected behavior

The published OpenAPI spec should match the live wire contract.

A private message is associated with this bug report

1 Like