{"openapi":"3.1.0","info":{"title":"Realtime","description":"Provides real-time updates from the Key/Value Store via WebSockets. Ideal for live data synchronization between game clients and backend services.","version":"0.1.0"},"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer"},"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key"}},"schemas":{"organizationAndProjectAndWorldHeader":{"description":"Organization, Project and World headers","type":"object","properties":{"x-m2-organization-id":{"description":"The ID of an organization","type":"string"},"x-m2-project-id":{"description":"The ID of a project","type":"string"},"x-m2-world-id":{"description":"The ID of a world","type":"string"}},"required":["x-m2-organization-id","x-m2-project-id","x-m2-world-id"]},"organizationId":{"description":"The ID of an organization","type":"string"},"projectId":{"description":"The ID of a project","type":"string"},"organizationAndOptionalProjectAndOptionalWorldHeader":{"description":"Organization, optional Project and optional World headers","type":"object","properties":{"x-m2-organization-id":{"description":"The ID of an organization","type":"string"},"x-m2-project-id":{"description":"The ID of a project","type":"string"},"x-m2-world-id":{"description":"The ID of a world","type":"string"}},"required":["x-m2-organization-id"]},"realtimeWarningResponse":{"description":"The warning response from the realtime service websocket","type":"object","properties":{"warning":{"description":"The warning being provided to the user","type":"string"},"message":{"description":"The message being provided to the user","type":"string"},"resource":{"description":"The resource being subscribed to","type":"object","properties":{"type":{"type":"string"},"id":{"type":"string"}},"required":["type","id"]},"userId":{"type":"string"}},"required":["warning","message","resource","userId"]},"realtimeWarning":{"description":"The warning being provided to the user","type":"string"},"realtimeMessage":{"description":"The message being provided to the user","type":"string"},"realtimeResource":{"description":"The resource being subscribed to","type":"object","properties":{"type":{"type":"string"},"id":{"type":"string"}},"required":["type","id"]},"realtimeErrorResponse":{"description":"The error response from the realtime service websocket","type":"object","properties":{"error":{"description":"The error being provided to the user","type":"string"},"message":{"description":"The message being provided to the user","type":"string"},"resource":{"$ref":"#/components/schemas/realtimeResource"},"userId":{"type":"string"}},"required":["error","message","userId"]},"realtimeError":{"description":"The error being provided to the user","type":"string"},"apiError":{"description":"The error object returned by the API when an error occurs","type":"object","properties":{"error":{"description":"HTTP error message","type":"string"},"code":{"description":"Fastify error code","type":"string"},"message":{"description":"User error message","type":"string"},"statusCode":{"description":"HTTP status code","type":"number"}},"required":["error","message","statusCode"]},"httpError":{"description":"HTTP error message","type":"string"},"errorCode":{"description":"Fastify error code","type":"string"},"errorMessage":{"description":"User error message","type":"string"},"errorStatusCode":{"description":"HTTP status code","type":"number"},"statusMessage":{"description":"Provides information about the service status.","type":"string"},"UserBalanceMessage":{"description":"Message sent by the user balance websocket","type":"object","properties":{"type":{"anyOf":[{"type":"string","enum":["user_not_found"]},{"type":"string","enum":["no_verified_wallet"]},{"type":"string","enum":["refresh_collection"]},{"type":"string","enum":["internal_error"]}]}},"required":["type"]}}},"paths":{"/connect/":{"get":{"operationId":"connect","summary":"Connect to the realtime service","tags":["Realtime"],"description":"Creates a websocket connection to the realtime service, sending messages to the realtime service\nwill subscribe you to different resources allowing you to listen to document updates in realtime. When subscribing if a\nresource doesn't exist yet a listener will be created and will be triggered when the resource is created. If the resource\nis deleted the listener will still exist so make sure to unsubscribe when you no longer need the resource.\n\nWhen connecting via a html websocket you will need to parse all of your headers in through `Sec-WebSocket-Protocol`\nwhich is an optional header that takes in a string. Format for the string needs to be a list of headers split by \\n and\nkey value split by : and then encoded into base58\n\nExample format\n\nx-m2-organization:testOrg\nx-m2-project:testProj\n\n\nExample messages for subscribing to the resources available in the realtime service -\n\n* KVStore:\n\n        {\n            \"action\": \"subscribe\",\n            \"resource\": {\n                \"type\": \"kvStore\",\n                \"id\": \"World:kvstoreClient:testKey\"\n            }\n        }\n\n* Collections:\n\n        {\n            \"action\": \"subscribe\",\n            \"resource\": {\n                \"type\": \"collection\",\n                \"id\": \"public\"\n            }\n        }\n\n* Liveconfig:\n\n        {\n            \"action\": \"subscribe\",\n            \"resource\": {\n                \"type\": “liveConfig\",\n                \"id\": “game\"\n            }\n        }\n\nUsing the same format, you can also unsubscribe from the resources by changing the action to \"unsubscribe\" and sending the same resource.\n\nExample response formats below.\n\n## Success:\n\n        {\n          \"userId\": \"fakeUserId\",\n          \"resource\": {\n              \"type\": \"collection\",\n              \"id\": \"private\"\n          },\n          \"data\": {\n              \"userId\": \"fakeUserId\",\n              \"datasourceId\": \"fakeDatasourceId\",\n              \"userCollection\": []\n          },\n          \"version\": \"2024-01-30T15:50:35.742Z\"\n        }\n\n## Warning:\n\n        {\n          \"warning\": \"resource_not_found\",\n          \"message\": \"KVStore resource doesn't currently exist, subscription was still made successfully\"\n        }\n\n## Error:\n\n        {\n          \"error\": \"Invalid message format\"\n        }\n  ","parameters":[{"schema":{"type":"string"},"in":"header","name":"x-m2-organization-id","required":true,"description":"The ID of an organization"},{"schema":{"type":"string"},"in":"header","name":"x-m2-project-id","required":false,"description":"The ID of a project"},{"schema":{"type":"string"},"in":"header","name":"x-m2-world-id","required":false,"description":"The ID of a world"}],"security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"responses":{"101":{"description":"Default Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/statusMessage"},{"$ref":"#/components/schemas/realtimeWarningResponse"},{"$ref":"#/components/schemas/realtimeErrorResponse"}]}}}},"4XX":{"description":"The error object returned by the API when an error occurs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiError"}}}}}}}},"servers":[{"url":"https://{organizationId}.m2worlds.io/api/realtime","variables":{"organizationId":{"default":"your-organization-id"}}}],"security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}]}