> For the complete documentation index, see [llms.txt](https://developer.abacum.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.abacum.ai/essentials/code-samples.md).

# Code samples

Get a token and read data with curl, Python and JavaScript.

Each sample gets an access token, then calls `GET /public-api/me` and `GET /public-api/models`. Replace `CLIENT_ID` and `CLIENT_SECRET` with the credentials you created in [Get credentials](/essentials/get-credentials.md).

The user that owns the credentials must be an Admin or Super Admin to list models. See [Access and permissions](/essentials/concepts/access-and-permissions.md).

{% tabs %}
{% tab title="curl" %}

```bash
TOKEN=$(curl -s -X POST https://api.abacum.io/server-authentication/oauth2/token/ \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET" \
  | jq -r .access_token)

curl -s https://api.abacum.io/public-api/me \
  -H "Authorization: Bearer $TOKEN"

curl -s https://api.abacum.io/public-api/models \
  -H "Authorization: Bearer $TOKEN"
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

BASE_URL = "https://api.abacum.io"

token = requests.post(
    f"{BASE_URL}/server-authentication/oauth2/token/",
    data={
        "grant_type": "client_credentials",
        "client_id": "CLIENT_ID",
        "client_secret": "CLIENT_SECRET",
    },
    timeout=30,
).json()["access_token"]

headers = {"Authorization": f"Bearer {token}"}

me = requests.get(f"{BASE_URL}/public-api/me", headers=headers, timeout=30)
print(me.json())
print(me.headers["X-Request-ID"])

models = requests.get(f"{BASE_URL}/public-api/models", headers=headers, timeout=30)
print(models.json()["data"])
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const BASE_URL = "https://api.abacum.io";

const tokenResponse = await fetch(`${BASE_URL}/server-authentication/oauth2/token/`, {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: new URLSearchParams({
    grant_type: "client_credentials",
    client_id: "CLIENT_ID",
    client_secret: "CLIENT_SECRET",
  }),
});
const { access_token } = await tokenResponse.json();

const headers = { Authorization: `Bearer ${access_token}` };

const me = await fetch(`${BASE_URL}/public-api/me`, { headers });
console.log(await me.json());
console.log(me.headers.get("X-Request-ID"));

const models = await fetch(`${BASE_URL}/public-api/models`, { headers });
console.log((await models.json()).data);
```

{% endtab %}
{% endtabs %}

Every response from a `/public-api/` endpoint carries an `X-Request-ID` header. Log it next to each call. Support asks for it when you report a problem. See [Errors](/essentials/concepts/errors.md).

## Read model data

Data endpoints return a link to a file, not the rows. This example reads the actuals of one model for the first quarter of 2024, then downloads the file.

{% tabs %}
{% tab title="Python" %}

```python
import requests

BASE_URL = "https://api.abacum.io"
MODEL_ID = "MODEL_ID"  # an id from GET /public-api/models

response = requests.get(
    f"{BASE_URL}/public-api/models/{MODEL_ID}/actuals_data",
    headers=headers,
    params={"start_date": "2024-01", "end_date": "2024-03", "enrich": "true"},
    timeout=60,
)
response.raise_for_status()

download_url = response.json()["data"]
with open("actuals.csv", "wb") as file:
    file.write(requests.get(download_url, timeout=120).content)
```

{% endtab %}

{% tab title="curl" %}

```bash
URL=$(curl -s "https://api.abacum.io/public-api/models/MODEL_ID/actuals_data?start_date=2024-01&end_date=2024-03&enrich=true" \
  -H "Authorization: Bearer $TOKEN" | jq -r .data)

curl -s "$URL" -o actuals.csv
```

{% endtab %}
{% endtabs %}

The link lasts 30 minutes for CSV and 2 hours for Parquet. See [Download links](/essentials/concepts/download-links.md).
