# Run your first warehouse query

> Obtain a real data-model slug, send a bounded factQuery with variables, and verify empty or populated GraphQL results.

Obtain a real data-model slug through JSON:API, then send a bounded GraphQL
query. A model with no persisted facts returns an empty `results` array; that is
a valid query but not proof that a workflow has written records.

## What you will do

1. List the visible data models and choose one real slug.
2. Write a GraphQL query and variables to a temporary JSON request file.
3. Request at most ten latest rows.
4. Verify the GraphQL data/error shape and version headers.

## Prerequisites

- Create a model through the Warehouse product flow described in
  [Data models](/help/data-dashboards/data-models).
- For a populated result, run a workflow whose harmonizer persists facts for
  that model.
- Use a service account in the same workspace with `api_read` and an active
  run-as member.
- Set `HODOFLOW_BASE_URL` and `TOKEN`; install cURL and `jq`.

Do not invent a slug from a display name. The stored slug is the GraphQL table
identity.

## Request

List the visible data models. This collection currently does not expose a
pagination parameter, so it is the documented exception to the portal's
explicit-limit rule. Use the response only to select a real slug:

```bash
MODELS_RESPONSE="$(
  curl --silent --show-error --globoff \
    --header "Accept: application/vnd.api+json" \
    --header "Authorization: Bearer $TOKEN" \
    "$HODOFLOW_BASE_URL/api/json/v1/data_models?fields[data_model]=name,slug"
)"

printf '%s\n' "$MODELS_RESPONSE" | jq '.data[] | {name: .attributes.name, slug: .attributes.slug}'
DATA_MODEL_SLUG="$(printf '%s\n' "$MODELS_RESPONSE" | jq -er '.data[0].attributes.slug')"
```

Create a request file. Query and variables stay separate, which avoids escaping
nested values by hand:

```bash
QUERY_FILE="$(mktemp)"

jq -n --arg slug "$DATA_MODEL_SLUG" '{
  query: "query FirstFacts($slug: String!, $limit: Int!) { factQuery(dataModelSlug: $slug, mode: \"latest\", limit: $limit) { count hasNextPage results { entityId observedAt data } } }",
  variables: {slug: $slug, limit: 10}
}' > "$QUERY_FILE"

curl --silent --show-error --include \
  --request POST \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer $TOKEN" \
  --data-binary "@$QUERY_FILE" \
  "$HODOFLOW_BASE_URL/api/graphql"
```

You should see `200`, a date-based `x-api-version`, `x-request-id`, and either a
`data.factQuery` object or a GraphQL `errors` array explaining why resolution
did not succeed.

## Expected response

A valid model with no matching facts returns:

```json
{
  "data": {
    "factQuery": {
      "count": 0,
      "hasNextPage": false,
      "results": []
    }
  }
}
```

A populated result contains at most ten `Fact` rows:

```json
{
  "data": {
    "factQuery": {
      "count": 1,
      "hasNextPage": false,
      "results": [
        {
          "entityId": "order-123",
          "observedAt": "2026-07-31T18:30:00Z",
          "data": { "status": "shipped", "total": 125.5 }
        }
      ]
    }
  }
}
```

Field names inside `data` come from your model; they are not a fixed schema in
this guide.

## Troubleshooting

- Empty model list: create a data model in the same workspace first.
- Unknown slug error: re-read `.attributes.slug`; names and slugs differ.
- `401`: exchange once and retry once.
- `403`: `factQuery` requires `api_read` and an active run-as member.
- Complexity error: reduce `limit` or selected fields.
- Empty `results`: confirm a workflow persisted facts for this exact model and
  workspace. An empty result is not an authentication failure.
- `429`: obey `Retry-After` before retrying.

Remove the temporary file and local response values:

```bash
rm "$QUERY_FILE"
unset QUERY_FILE MODELS_RESPONSE DATA_MODEL_SLUG
```

## Next steps

- Compare [latest and timeline semantics](/graphql/fact-query).
- Add variables-based [filters and pagination](/graphql/filters-pagination-limits).
- Browse the exact [factQuery reference](/reference/graphql/fact-query).
