diff --git a/guides/api.md b/guides/api.md index f8e7f1502..92422d80f 100644 --- a/guides/api.md +++ b/guides/api.md @@ -1,7 +1,7 @@ # Hubs Server API Reticulum includes a [GraphQL](https://graphql.org/) API that grants programmatic access to server resources. -Note: This API is currently in alpha testing and is not yet available for use. (Users cannot generate API Access Tokens.) +Note: This API is not yet stable, and may undergo breaking changes in future updates. ## Accessing the API Hubs Cloud administrators can enable or disable the API by toggling `App Settings > Features > Public API Access` in the admin panel. @@ -13,7 +13,9 @@ You must attach an API Access Token with each request. To attach an API Access Token to a request, add an `HTTP` header named `Authorization` with value `Bearer: `. -### API Access Token Types +### API Access Token Generation and Types +API Token can be generated and revoked though an interface located at `/tokens`. + There are two types of API Access Tokens: - `:account` tokens act on behalf of a specific user - `:app` tokens act on behalf of the Hubs Cloud itself @@ -31,10 +33,15 @@ Scopes, actions, and token types are expected to expand over time. ## Examples Reticulum ships with [GraphiQL](https://github.com/graphql/graphiql/tree/main/packages/graphiql#graphiql), a graphical, interactive, in-browser GraphQL IDE that makes it easier to test and learn the API. It can be accessed by navigating to `/api/v2_alpha/graphiql`. -[This example workspace](../test/api/v2/graphiql-workspace-2020-12-07-15-26-56.json) demonstrates several queries and can be loaded into the GraphiQL interface. You will have to supply your own API access token(s). +[This example workspace](../test/api/v2/graphiql-workspace-2023-02-17-11-24-40.json) demonstrates several queries and can be loaded into the GraphiQL interface. In the workspace, you will have to supply your own API access token(s) (see `TOKENUPDATEME` in file) and the host name of your deployment (see `HOSTUPDATEME` in file). Requests can also be sent by - an `HTTP` client library, - a command line tool like `curl`, - a GraphQL-specific client library, or - any other tool that speaks `HTTP`. + +## What Can You Read and Write +GraphQL includes [handy introspection tools](https://graphql.org/learn/introspection/) which you can accessed through the IDE. The sample workspace above includes examples of introspection queries to learn about the parameters which can be manipulated through the API. + +See [room_types.ex](../lib/ret_web/schema/room_types.ex) for full GraphQL Schema. diff --git a/test/api/v2/graphiql-workspace-2023-02-17-11-24-40.json b/test/api/v2/graphiql-workspace-2023-02-17-11-24-40.json new file mode 100644 index 000000000..aa953d070 --- /dev/null +++ b/test/api/v2/graphiql-workspace-2023-02-17-11-24-40.json @@ -0,0 +1,137 @@ +{ + "key": "graphiql", + "lastId": 9, + "tabIds": [ + "tab2", + "tab3", + "tab5", + "tab8", + "tab9" + ], + "closedTabs": [], + "defaultUrl": "https://HOSTUPDATEME/api/v2_alpha/graphiql", + "defaultWebsocketUrl": "", + "defaultQuery": "", + "defaultVariables": "", + "defaultProxy": false, + "defaultHeaders": [ + { + "name": "authorization", + "value": "TOKENUPDATEME" + } + ], + "usedUrls": [], + "recentHeaders": [], + "maxTabHistory": 20, + "maxUrlHistory": 20, + "maxHistory": 20, + "savedQueries": [], + "activeId": "tab9", + "tabs": [ + { + "id": "tab2", + "name": "queries", + "websocketUrl": "", + "proxy": false, + "collapsed": false, + "maxHistory": 20, + "url": "https://HOSTUPDATEME/api/v2_alpha/graphiql", + "headers": [ + { + "name": "authorization", + "value": "TOKENUPDATEME" + } + ], + "history": [], + "graphiql:query": "query {\n myRooms(page: 1, pageSize: 3) {\n entries {\n name,\n description,\n id,\n memberPermissions{\n fly\n },\n creatorAssignmentToken,\n defaultEnvironmentGltfBundleUrl,\n scene {\n ... on Scene {\n name,\n id\n }\n ... on SceneListing{\n name,\n id\n }\n }\n }\n }\n \n favoriteRooms(page: 1, pageSize: 3) {\n entries {\n name,\n id,\n memberPermissions{\n fly\n }\n defaultEnvironmentGltfBundleUrl,\n scene {\n ... on Scene {\n name,\n id\n }\n ... on SceneListing{\n name,\n id\n }\n }\n }\n }\n \n publicRooms(page: 1, pageSize: 3) {\n entries {\n name,\n id,\n memberPermissions{\n fly\n }\n defaultEnvironmentGltfBundleUrl,\n scene {\n ... on Scene {\n name,\n id\n }\n ... on SceneListing{\n name,\n id\n }\n }\n }\n }\n}", + "graphiql:queries": "{\"queries\":[{\"query\":\"query {\\n myRooms(page: 2, pageSize: 5) {\\n entries {\\n name,\\n id,\\n memberPermissions{\\n fly\\n }\\n }\\n }\\n}\",\"variables\":\"\"},{\"query\":\"query {\\n publicRooms(page: 2, pageSize: 5) {\\n entries {\\n name,\\n id,\\n memberPermissions{\\n fly\\n }\\n }\\n }\\n}\"},{\"query\":\"query {\\n publicRooms(page: 1, pageSize: 5) {\\n entries {\\n name,\\n id,\\n memberPermissions{\\n fly\\n }\\n }\\n }\\n}\"},{\"query\":\"query {\\n myRooms(page: 1, pageSize: 3) {\\n entries {\\n name,\\n id,\\n memberPermissions{\\n fly\\n }\\n }\\n }\\n \\n favoriteRooms(page: 1, pageSize: 3) {\\n entries {\\n name,\\n id,\\n memberPermissions{\\n fly\\n }\\n }\\n }\\n \\n publicRooms(page: 1, pageSize: 3) {\\n entries {\\n name,\\n id,\\n memberPermissions{\\n fly\\n }\\n }\\n }\\n}\"},{\"query\":\"query {\\n myRooms(page: 1, pageSize: 3) {\\n entries {\\n name,\\n description,\\n id,\\n memberPermissions{\\n fly\\n }\\n }\\n }\\n \\n favoriteRooms(page: 1, pageSize: 3) {\\n entries {\\n name,\\n id,\\n memberPermissions{\\n fly\\n }\\n }\\n }\\n \\n publicRooms(page: 1, pageSize: 3) {\\n entries {\\n name,\\n id,\\n memberPermissions{\\n fly\\n }\\n }\\n }\\n}\"},{\"query\":\"query {\\n myRooms(page: 1, pageSize: 3) {\\n entries {\\n name,\\n description,\\n id,\\n memberPermissions{\\n fly\\n },\\n scene {\\n ...on Scene {\\n name,\\n id\\n }\\n }\\n }\\n }\\n \\n favoriteRooms(page: 1, pageSize: 3) {\\n entries {\\n name,\\n id,\\n memberPermissions{\\n fly\\n }\\n }\\n }\\n \\n publicRooms(page: 1, pageSize: 3) {\\n entries {\\n name,\\n id,\\n memberPermissions{\\n fly\\n }\\n }\\n }\\n}\"},{\"query\":\"query {\\n myRooms(page: 1, pageSize: 3) {\\n entries {\\n name,\\n description,\\n id,\\n memberPermissions{\\n fly\\n },\\n defaultEnvironmentGltfBundleUrl,\\n scene {\\n ... on Scene {\\n name,\\n id\\n }\\n ... on SceneListing{\\n name,\\n id\\n }\\n }\\n }\\n }\\n \\n favoriteRooms(page: 1, pageSize: 3) {\\n entries {\\n name,\\n id,\\n memberPermissions{\\n fly\\n }\\n defaultEnvironmentGltfBundleUrl,\\n scene {\\n ... on Scene {\\n name,\\n id\\n }\\n ... on SceneListing{\\n name,\\n id\\n }\\n }\\n }\\n }\\n \\n publicRooms(page: 1, pageSize: 3) {\\n entries {\\n name,\\n id,\\n memberPermissions{\\n fly\\n }\\n defaultEnvironmentGltfBundleUrl,\\n scene {\\n ... on Scene {\\n name,\\n id\\n }\\n ... on SceneListing{\\n name,\\n id\\n }\\n }\\n }\\n }\\n}\"},{\"query\":\"query {\\n myRooms(page: 1, pageSize: 3) {\\n entries {\\n name,\\n description,\\n id,\\n memberPermissions{\\n fly\\n },\\n creatorAssignmentToken,\\n defaultEnvironmentGltfBundleUrl,\\n scene {\\n ... on Scene {\\n name,\\n id\\n }\\n ... on SceneListing{\\n name,\\n id\\n }\\n }\\n }\\n }\\n \\n favoriteRooms(page: 1, pageSize: 3) {\\n entries {\\n name,\\n id,\\n memberPermissions{\\n fly\\n }\\n defaultEnvironmentGltfBundleUrl,\\n scene {\\n ... on Scene {\\n name,\\n id\\n }\\n ... on SceneListing{\\n name,\\n id\\n }\\n }\\n }\\n }\\n \\n publicRooms(page: 1, pageSize: 3) {\\n entries {\\n name,\\n id,\\n memberPermissions{\\n fly\\n }\\n defaultEnvironmentGltfBundleUrl,\\n scene {\\n ... on Scene {\\n name,\\n id\\n }\\n ... on SceneListing{\\n name,\\n id\\n }\\n }\\n }\\n }\\n}\"}]}", + "graphiql:docExplorerWidth": 350, + "graphiql:variableEditorHeight": 200, + "graphiql:editorFlex": 1 + }, + { + "id": "tab3", + "name": "createRoom", + "websocketUrl": "", + "proxy": false, + "headers": [ + { + "name": "authorization", + "value": "TOKENUPDATEME" + } + ], + "url": "https://HOSTUPDATEME/api/v2_alpha/graphiql", + "collapsed": false, + "maxHistory": 20, + "history": [], + "graphiql:query": "mutation {\n createRoom(description: \"A room with a view\", allowPromotion:false) {\n id,\n name,\n allowPromotion,\n memberPermissions{\n fly\n },\n embedToken,\n creatorAssignmentToken,\n roomSize\n }\n}", + "graphiql:queries": "{\"queries\":[{\"query\":\"mutation {\\n createRoom(description: \\\"A room with a view\\\") {\\n id\\n }\\n}\",\"variables\":\"\"},{\"query\":\"mutation {\\n createRoom(description: \\\"A room with a view\\\") {\\n id,\\n name\\n }\\n}\",\"variables\":\"\"},{\"query\":\"mutation {\\n createRoom(description: \\\"A room with a view\\\") {\\n id,\\n name,\\n allowPromotion,\\n memberPermissions{\\n fly\\n }\\n }\\n}\"},{\"query\":\"mutation {\\n createRoom(description: \\\"A room with a view\\\") {\\n id,\\n name,\\n allowPromotion,\\n memberPermissions{\\n fly\\n },\\n embedToken\\n }\\n}\"},{\"query\":\"mutation {\\n createRoom(description: \\\"A room with a view\\\", allowPromotion:false) {\\n id,\\n name,\\n allowPromotion,\\n memberPermissions{\\n fly\\n },\\n embedToken\\n }\\n}\"},{\"query\":\"mutation {\\n createRoom(description: \\\"A room with a view\\\", allowPromotion:false) {\\n id,\\n name,\\n allowPromotion,\\n memberPermissions{\\n fly\\n },\\n embedToken,\\n creatorAssignmentToken\\n }\\n}\"},{\"query\":\"mutation {\\n createRoom(description: \\\"A room with a view\\\", allowPromotion:false) {\\n id,\\n name,\\n allowPromotion,\\n memberPermissions{\\n fly\\n },\\n embedToken,\\n creatorAssignmentToken,\\n roomSize\\n }\\n}\"}]}", + "graphiql:variableEditorHeight": 200, + "graphiql:editorFlex": 1, + "graphiql:docExplorerWidth": 350 + }, + { + "id": "tab5", + "name": "updateRoom", + "websocketUrl": "", + "proxy": false, + "headers": [ + { + "name": "authorization", + "value": "TOKENUPDATEME" + } + ], + "url": "https://HOSTUPDATEME/api/v2_alpha/graphiql", + "collapsed": false, + "maxHistory": 20, + "history": [], + "graphiql:query": "mutation {\n updateRoom(id: \"7VkWtfB\", description: \"A room with an APP view\") {\n description,\n id,\n name,\n allowPromotion,\n memberPermissions{\n fly\n },\n embedToken\n }\n}", + "graphiql:variableEditorHeight": 200, + "graphiql:editorFlex": 1, + "graphiql:queries": "{\"queries\":[{\"query\":\"mutation {\\n createRoom(description: \\\"A room with a view\\\") {\\n id,\\n name,\\n allowPromotion,\\n memberPermissions{\\n fly\\n },\\n embedToken\\n }\\n}\",\"variables\":\"\"},{\"query\":\"mutation {\\n updateRoom(id: \\\"EzqydXp\\\", description: \\\"Aasddas view\\\") {\\n description,\\n id,\\n name,\\n allowPromotion,\\n memberPermissions{\\n fly\\n },\\n embedToken\\n }\\n}\",\"variables\":\"\"},{\"query\":\"mutation {\\n updateRoom(id: \\\"maJCnRD\\\", description: \\\"Aasddas view\\\") {\\n description,\\n id,\\n name,\\n allowPromotion,\\n memberPermissions{\\n fly\\n },\\n embedToken\\n }\\n}\",\"variables\":\"\"},{\"query\":\"mutation {\\n updateRoom(id: \\\"maJCnRD\\\", description: \\\"fffff view\\\") {\\n description,\\n id,\\n name,\\n allowPromotion,\\n memberPermissions{\\n fly\\n },\\n embedToken\\n }\\n}\",\"variables\":\"\"},{\"query\":\"mutation {\\n updateRoom(id: \\\"maJCnRD\\\", description: \\\"fggggg view\\\") {\\n description,\\n id,\\n name,\\n allowPromotion,\\n memberPermissions{\\n fly\\n },\\n embedToken\\n }\\n}\",\"variables\":\"\"},{\"query\":\"mutation {\\n updateRoom(id: \\\"maJCnRD\\\", description: \\\"A room with an APP view\\\") {\\n description,\\n id,\\n name,\\n allowPromotion,\\n memberPermissions{\\n fly\\n },\\n embedToken\\n }\\n}\"},{\"query\":\"mutation {\\n updateRoom(id: \\\"7VkWtfB\\\", description: \\\"A room with an APP view\\\") {\\n description,\\n id,\\n name,\\n allowPromotion,\\n memberPermissions{\\n fly\\n },\\n embedToken\\n }\\n}\"}]}", + "graphiql:docExplorerWidth": 350 + }, + { + "id": "tab8", + "name": "introspection more", + "url": "https://HOSTUPDATEME/api/v2_alpha/graphiql", + "websocketUrl": "", + "proxy": false, + "headers": [ + { + "name": "authorization", + "value": "TOKENUPDATEME" + } + ], + "collapsed": false, + "maxHistory": 20, + "history": [], + "graphiql:query": "query {\n __schema {\n types {\n name\n kind\n fields {\n name\n description\n type {\n name\n }\n }\n }\n }\n}", + "graphiql:variables": "", + "graphiql:editorFlex": 1, + "graphiql:variableEditorHeight": 200, + "graphiql:docExplorerWidth": 350 + }, + { + "id": "tab9", + "name": "introspection less", + "url": "https://HOSTUPDATEME/api/v2_alpha/graphiql", + "websocketUrl": "", + "proxy": false, + "headers": [ + { + "name": "authorization", + "value": "TOKENUPDATEME" + } + ], + "collapsed": false, + "maxHistory": 20, + "history": [], + "graphiql:query": "query {\n __schema {\n types {\n name\n description\n } \n }\n}", + "graphiql:variables": "", + "graphiql:editorFlex": 1, + "graphiql:variableEditorHeight": 200, + "graphiql:docExplorerWidth": 350 + } + ] +}