> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tappify.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# useTapQuery

> Reads one query's worth of the owner's Tappify data, cached per install, query and filter bar.

```ts theme={null}
function useTapQuery<Q>(query, options?): TapQueryResult<TapResult<Q>>;
```

Reads one query's worth of the owner's Tappify data, cached per install, query
and filter bar.

## Type Parameters

### Q

`Q` *extends* [`TapQuery`](/extensions/reference/frontend-api/TypeAlias.TapQuery)

## Parameters

### query

`Q`

### options?

[`TapQueryOptions`](/extensions/reference/frontend-api/Interface.TapQueryOptions) = `{}`

## Returns

[`TapQueryResult`](/extensions/reference/frontend-api/Interface.TapQueryResult)\<[`TapResult`](/extensions/reference/frontend-api/TypeAlias.TapResult)\<`Q`>>

## Remarks

Each kind needs its own scope — `project` needs `projects:read`, `series` needs
`analytics:read`, `keywords` and `listing` need `store.metadata:read`, and
`reviews`, `crashes` and `revenue` need their own. A kind the install has not
granted comes back as a `TapError` with code `TAP_SCOPE_MISSING` in `error`. An
answer stays fresh for 30 seconds and a failed read is not retried, so
`refetch` is yours to call. The host adds only the country filter to the read:
pass `range` into a `series`, `reviews`, `crashes` or `revenue` query yourself,
and `platform` into a `series` query, which is the only kind that takes one.
Throws `TAP_NO_QUERY_CLIENT` when no Tappify mount provides the query client.

## Examples

```tsx theme={null}
import { TapStat, useTapFilters, useTapQuery } from '@tappify/extension-sdk';

function Downloads() {
  const filters = useTapFilters();
  const downloads = useTapQuery(
    { kind: 'series', metric: 'downloads', range: filters.range },
    { invalidateOn: ['release.shipped'] },
  );
  const points = downloads.data?.points ?? [];
  const total = points.reduce((sum, point) => sum + point.value, 0);
  return <TapStat label="Downloads" value={total} />;
}
```

```tsx theme={null}
import { TapTable, useTapQuery } from '@tappify/extension-sdk';

function Keywords() {
  const keywords = useTapQuery({ kind: 'keywords' });
  return (
    <TapTable
      columns={[
        { key: 'term', label: 'Term' },
        { key: 'position', label: 'Rank', align: 'end' },
      ]}
      rows={keywords.data?.keywords ?? []}
      rowKey={keyword => keyword.id}
    />
  );
}
```
