> ## 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.

# useTapServer

> Calls one procedure on your own server, cached per install, name, input and filter bar.

```ts theme={null}
function useTapServer<N>(
   name, 
   input, 
   options?
): TapQueryResult<unknown>;
```

Calls one procedure on your own server, cached per install, name, input and
filter bar.

## Type Parameters

### N

`N` *extends* `string`

## Parameters

### name

`N`

### input

`unknown`

### options?

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

## Returns

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

## Remarks

The name and the input are narrowed by the `TapProcedureMap` augmentation
`tappify extension types` writes, so a procedure the manifest does not declare
does not compile; at runtime a name the host has no route for throws
`TAP_UNKNOWN_PROCEDURE`. The call carries the whole filter bar for you. An
answer stays fresh for 30 seconds and a failure is not retried; an error your
server threw arrives as a `TapServerError` with your own `code`. Throws
`TAP_NO_QUERY_CLIENT` when no Tappify mount provides the query client.

## Example

```tsx theme={null}
import { TapButton, TapErrorState, useTapFilters, useTapServer } from '@tappify/extension-sdk';

function Summary() {
  const filters = useTapFilters();
  const summary = useTapServer(
    'getSummary',
    { days: 7, platform: filters.platform },
    { invalidateOn: ['settings.changed'] },
  );
  if (summary.error !== null) {
    return <TapErrorState title="The summary did not load" description={summary.error.message} />;
  }
  return <TapButton loading={summary.isLoading} onClick={summary.refetch}>Refresh</TapButton>;
}
```
