Endpoints and queries

The BEEM API is a single GraphQL endpoint. Here's how to send requests, read this reference, and paginate through results.

There is no /v1/datasets or /users/me — those concepts exist as fields inside the GraphQL schema, not as separate REST paths. Every operation, read or write, goes through one URL.

The endpoint

POST https://api.beemdata.com/graphql

Request shape

Every request is a POST with Content-Type: application/json and a body of three fields:

{
  "query": "query GetWorkspace($id: ID!) { getWorkspace(id: $id) { id name } }",
  "operationName": "GetWorkspace",
  "variables": { "id": "..." }
}
FieldRequiredDescription
queryyesThe GraphQL operation document. May contain multiple operations — operationName selects which to run.
operationNamerecommendedName of the operation in query to execute.
variablesdependsMap of variable name → value, matching the $variable placeholders in query.

A complete authenticated example:

TOKEN="<your access token>"

curl -X POST https://api.beemdata.com/graphql \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "query { listWorkspaces { items { id name } } }"
  }'

Reading this reference

This reference documents each GraphQL field — both queries and mutations — as its own page. Browse by resource (Datasets, Sources, Connections, etc.) under Queries & Mutations, or look up a type (Dataset, Workspace, Connection) under Types.

A few conventions:

  • Sidebar labels are raw GraphQL field names (getDataset, listDatasetsByWorkspace). The page header gives you the human-readable name.
  • Each operation page comes with a pre-filled query string. Copy-paste it as-is — you only need to fill in variables.
  • Type pages cross-link. Clicking a field type on a Type page jumps to that type's own page, so you can navigate the schema as a graph.

About the URLs you'll see

In Try It and the code samples, you'll see paths like POST /graphql/query/getDataset or POST /graphql/mutation/createDataset. These exist purely so this reference can render one page per operation — readme.io requires a unique URL per documented endpoint.

On the wire, every request goes to POST /graphql. The operation discriminator is in the request body (the query and operationName fields), not in the URL. Our edge layer rewrites /graphql/{kind}/{name}/graphql before forwarding to the API, so the URLs as shown will work regardless.

Sub-selections

Unlike REST, GraphQL requires you to specify exactly which fields you want back. The pre-filled queries in this reference include every scalar field of the return type — useful for exploration, but oversized for production. Trim the selection set to what you actually need:

# Pre-filled query — fetches every field
query GetDataset($id: ID!) {
  getDataset(id: $id) {
    id
    name
    description
    createdAt
    updatedAt
    workspace { id name organization { id name } }
    owner { id email }
    # ... 40 more fields
  }
}

# Trimmed for your actual use case
query GetDataset($id: ID!) {
  getDataset(id: $id) {
    id
    name
    workspace { id name }
  }
}

Smaller selection sets mean faster responses and less data over the wire — worth doing for high-traffic operations.

Pagination

Queries that return lists support cursor-based pagination via two arguments:

ArgumentDescription
limitMaximum number of items to return per page (default 25, max 100).
nextTokenPagination cursor returned by the previous request. Pass back in to get the next page.

The response is wrapped in a Connection object:

query ListDatasets($workspaceId: ID!, $nextToken: String) {
  listDatasetsByWorkspace(workspaceId: $workspaceId, limit: 50, nextToken: $nextToken) {
    items {
      id
      name
    }
    nextToken   # null when there are no more pages
  }
}

To fetch all results, loop until nextToken comes back null.

Versioning

The API is unversioned. Backwards-incompatible changes — removing a field, narrowing a type, making an optional argument required — are announced with at least 90 days' notice via the changelog. Additive changes (new fields, new operations, new optional arguments) ship without notice and don't require any client update.

If you depend on a field that isn't present in the response, the field was probably added after your client was built — refetch the schema or check the changelog.