# The session route, the user and the company

All calls go to `https://sandbox.api.platform.finbaze.com/graphql` with `Authorization: Bearer <server token>`. Get a server token by exchanging the key:

```ts
const BASE = process.env.FINBAZE_API_URL ?? "https://sandbox.api.platform.finbaze.com";
let token: { value: string; expiresAt: number } | null = null;

export async function serverToken() {
  if (token && token.expiresAt > Date.now() + 30_000) return token.value;
  const res = await fetch(`${BASE}/v2/oauth2/token`, {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({ grant_type: "client_credentials", client_secret: process.env.FINBAZE_SECRET_KEY }),
  });
  const body = await res.json();
  token = { value: body.access_token, expiresAt: Date.now() + body.expires_in * 1000 };
  return token.value;
}

export async function finbaze<T>(query: string, variables: Record<string, unknown> = {}): Promise<T> {
  const res = await fetch(`${BASE}/graphql`, {
    method: "POST",
    headers: { "content-type": "application/json", authorization: `Bearer ${await serverToken()}` },
    body: JSON.stringify({ query, variables }),
  });
  const body = await res.json();
  if (body.errors?.length) throw Object.assign(new Error(body.errors[0].message), { code: body.errors[0].extensions?.code });
  return body.data;
}
```

## The route

```ts
// app/api/finbaze/session/route.ts
import { finbaze } from "@/lib/finbaze";

export async function POST(request: Request) {
  // 1. Check the partner's own session here, and find the FinBaze company and user of the signed-in person.
  const { previousSessionId } = (await request.json().catch(() => ({}))) as { previousSessionId?: string };
  const data = await finbaze<{ createEmbedSession: { clientSecret: string } }>(
    `mutation($input: CreateEmbedSessionInput!) { createEmbedSession(input: $input) { clientSecret } }`,
    {
      input: {
        companyId: "<FinBaze company id of the signed-in user's company>",
        user: { externalUserId: "<the partner's id of the signed-in user>" },
        components: { taxCalendar: { enabled: true }, vatReturn: { enabled: true } },
        ...(previousSessionId ? { previousSessionId } : {}),
      },
    },
  );
  return Response.json({ clientSecret: data.createEmbedSession.clientSecret });
}
```

The keys of `components` are the camelCase session keys (`taxCalendar`, `vatReturn`, `bookingChip`, `notificationBanner`, …). Component features are chosen per component: `components: { vatReturn: { enabled: true, features: { submit: false } } }`.

## The company and the user (once, from the server)

```graphql
mutation { createPlatformCompany(input: { externalId: "biz-1001", registrationCountry: NL, registrationNumber: "12345678" }) { company { id } created } }
mutation { upsertPlatformUser(input: { externalUserId: "user-42", firstName: "Sam", lastName: "Jansen" }) { id } }
mutation { setPlatformUserAccess(input: { externalUserId: "user-42", profileId: "<company id>", role: admin }) { profileId role } }
```

`externalId` and `externalUserId` are the partner's own ids; calling again with the same id returns the same object. In the sandbox, `seedTestCompany(input: { template: nl_eenmanszaak_services })` creates a demo company with history.
