# Authentication

> Create a Business token in the app, send it as a bearer token, and understand its scope and lifetime.

Every request to the F-sąskaita API is authenticated with a **Business token**. The token identifies one business in your account, and every invoice, expense or profile you touch belongs to that business.

## Create a token

1. Sign in to [app.fsaskaita.lt](https://app.fsaskaita.lt) as a user who can manage the business.
2. Open **Settings**, then **Integrations**, then **API**.
3. Give the token a name that tells you where it is used, such as `accounting-sync`, and create it.
4. Copy the token immediately. It is shown once. Afterwards only its name is listed.

Tokens are only available on plans that include the API feature. If the section shows an upgrade notice instead of the form, the current plan does not include it.

## Use the token

Send it in the `Authorization` header and always request JSON:

```bash tab="cURL" tab-group="request"
curl https://app.fsaskaita.lt/api/profile \
  -H "Authorization: Bearer $FSASKAITA_TOKEN" \
  -H "Accept: application/json"
```

```js tab="JavaScript" tab-group="request"
const response = await fetch('https://app.fsaskaita.lt/api/profile', {
  headers: {
    Authorization: `Bearer ${process.env.FSASKAITA_TOKEN}`,
    Accept: 'application/json',
  },
});

console.log(response.status, await response.json());
```

```go tab="Go" tab-group="request"
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.fsaskaita.lt/api/profile", nil)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("FSASKAITA_TOKEN"))
	req.Header.Set("Accept", "application/json")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	body, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(body))
}
```

```python tab="Python" tab-group="request"
import os

import requests

response = requests.get(
    "https://app.fsaskaita.lt/api/profile",
    headers={
        "Authorization": f"Bearer {os.environ['FSASKAITA_TOKEN']}",
        "Accept": "application/json",
    },
)

print(response.status_code, response.json())
```

```java tab="Java" tab-group="request"
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class GetProfile {
    public static void main(String[] args) throws Exception {
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.fsaskaita.lt/api/profile"))
            .header("Authorization", "Bearer " + System.getenv("FSASKAITA_TOKEN"))
            .header("Accept", "application/json")
            .GET()
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());

        System.out.println(response.statusCode() + " " + response.body());
    }
}
```

```csharp tab="C#" tab-group="request"
using System.Net.Http.Headers;

using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
    "Bearer", Environment.GetEnvironmentVariable("FSASKAITA_TOKEN"));
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

var response = await client.GetAsync("https://app.fsaskaita.lt/api/profile");
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");
```

A successful response describes the business behind the token:

```json
{
  "data": {
    "business_id": "9c1f7b2e-3a6d-4d5e-9f0a-2b7c8d9e0f11",
    "business_title": "Pavyzdys, MB",
    "business_type": "small_partnership",
    "address": "Gedimino pr. 1, Vilnius",
    "vat_code": "LT100001234567",
    "company_name": "Pavyzdys, MB",
    "company_code": "305000001"
  }
}
```

For a business registered as individual activity the profile carries `individual_activity_id`, `first_name` and `last_name` instead of `company_name` and `company_code`.

## Why the Accept header matters

Application errors come back as JSON either way. Without `Accept: application/json`, however, a missing or revoked token answers with an HTML redirect to the login page, and a rate-limited request answers with an HTML error page. With the header you get `401 {"message":"Unauthenticated."}` and `429 {"message":"Too Many Attempts."}`.

## Scope and lifetime

- A token grants full access to its business. There are no per-endpoint permissions.
- Tokens do not expire. Revoke a token by deleting it in the same settings page; requests with a deleted token receive `401`.
- If your account has several businesses, create a separate token for each one.
- All tokens of one business share the same rate limit of 60 requests per minute.

## Keep it secret

Treat the token like a password. Store it in a secret manager or environment variable, never in a repository or in a browser-side application. If a token leaks, delete it in the app and create a new one.
