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

# Server functions

> Running code on the server

<Note>
  Not to be confused with [React Server
  Functions](https://react.dev/reference/rsc/server-functions); while they serve similar purposes,
  Attio server functions have different requirements and therefore do not follow the RSC protocol.
</Note>

Server functions allow you to get, update, or delete data from third-party
services, optionally using the user’s access token or secret. We do not
allow client-side fetch requests, so all HTTP requests to third-party services
must happen within server functions, which run inside a secure sandbox within
the Attio infrastructure. The server function runtime ***is not Node.js
compatible***, meaning some libraries that work in Node.js might not work in
our environment.

<Tip>The globals available to you are listed in [Available Globals](./available-globals).</Tip>

To add a server function to your app, you need to create a file with the `.server.ts` suffix. The file must `export` a `default async function`, which will serve as the
entry point for the server function. You can then import and call this function within the client
code.

Here is an example of using a server function to make
[a request](https://developers.outreach.io/api/reference/tag/Sequence-State/#tag/Sequence-State/paths/~1sequenceStates/post)
to Outreach on behalf of a user.

```tsx TypeScript theme={"system"}
// add-to-sequence.server.ts
import {getUserConnection} from "attio/server"

export default async function addToSequence({
  prospectId,
  sequenceId,
  mailboxId,
}: {
  prospectId: string
  sequenceId: number
  mailboxId: number
}): Promise<{id: string}> {
  const response = await fetch(`https://api.outreach.io/api/v2/sequenceStates`, {
    method: "POST",
    headers: {
      "Content-Type": "application/vnd.api+json",
      Authorization: `Bearer ${getUserConnection().value}`,
    },
    body: JSON.stringify({prospectId, sequenceId, mailboxId}),
  })

  if (!response.ok) {
    throw new Error(`Failed to add prospect to sequence: ${await response.text()}`)
  }

  // ℹ️ better to parse with a tool like Zod than to cast
  const body = (await response.json()) as {data: {id: string}}

  return body.data
}
```

Then, this `addToSequence()` function can be called from your client side code like:

```ts theme={"system"}
import addToSequence from "add-to-sequence.server.ts"

const sequenceState = await addToSequence({
  prospectId: "XXX",
  sequenceId: 42,
  mailboxId: 42,
})
```

As you can see, it’s possible to pass arguments and access the return value of a
server function. Each call to a server function makes a request to the Attio
infrastructure which is executed in a sandbox environment. Since we have to cross
a network boundary, ***it's only possible to pass JSON-serializable data*** between
client and server functions.

<Warning>
  Whatever you pass to or return from a server function will go through
  `JSON.stringify(JSON.parse(...))`.
</Warning>

If a server function throws an error, it is re-thrown on the client side and can be
handled with `try/catch` or `.catch`
[promise chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#chaining).

## Debugging

To check the output of `console.log()` calls from inside server functions, open the **Logs** tab for your app in the [developer dashboard](https://build.attio.com).

## Timeout

Server functions have a non-configurable 30 second timeout. If a server function takes longer than 30 seconds to complete, it will be terminated and a timeout error will be thrown.
