---
title: "Authentication with X-Api-Key"
description: "How to authenticate a V1 API call: X-Api-Key header, key lifecycle and documented 401 response."
canonical: https://factura.com.do/en/desarrolladores/autenticacion
lang: en
generator: factura.com.do docs-index
---

Authentication 

#  Every call carries an X-Api-Key header 

 factura.com.do does not use Bearer or OAuth for machine-to-machine integrations. An application key travels in the X-Api-Key header and is validated on every request. 

## The X-Api-Key header

| Field      | Value                                                              |
| ---------- | ------------------------------------------------------------------ |
| Name       | X-Api-Key                                                          |
| Location   | HTTP header on every request                                       |
| Format     | URL-safe base64 string (\~43 characters, no human-readable prefix) |
| Generation | Configuración → Acceso API → «Agregar», in the app                 |
| Plan       | Corporativo plan only; on other plans the key gets 403             |
| Validation | The server requires IsActive == true and ValidUntil >= now         |

## How to get your key

The key is issued from the app: in Configuración → **Acceso API** (Settings → API access), click «Agregar» and, in «Crear nueva llave API», enter the application name (for example, `ERP — production`) and the expiry date. The key stays in the credentials table, with a «Copiar» (copy) button; store it in your secrets manager. The section is only available on the Corporativo plan.

There is no public self-service issuance endpoint. If you need to rotate a key automatically, talk to the team to coordinate the flow.

Handling the key

Treat the X-Api-Key as a server secret. Never send it from a public client (browser, mobile app without a proxy). Anonymous API access without TLS is not supported.

## Your first authenticated call

The following snippet lists customers in the workspace using the key injected as an environment variable.

Your base URL: https://tuempresa.factura.com.do/api/v1

`tuempresa` is a placeholder: replace it with your workspace subdomain, the one you chose when you signed up and use to open the app. If you open the app at `https://tuempresa.factura.com.do`, your base URL is `https://tuempresa.factura.com.do/api/v1`. The API identifies your company by that subdomain: with any other host it cannot find your workspace and responds `404` with no body.

GET /api/v1/customers

cURL TypeScript Python PHP 

list-customers.sh

```

curl https://tuempresa.factura.com.do/api/v1/customers \

  -H "X-Api-Key: $FACTURA_API_KEY"


```

list-customers.ts

```

// list-customers.ts

const res = await fetch(

  "https://tuempresa.factura.com.do/api/v1/customers",

  { headers: { "X-Api-Key": process.env.FACTURA_API_KEY! } },

);

const { items, totalCount } = await res.json();


```

list\_customers.py

```

# list_customers.py

import os

import httpx


with httpx.Client(headers={"X-Api-Key": os.environ["FACTURA_API_KEY"]}) as c:

    r = c.get("https://tuempresa.factura.com.do/api/v1/customers")

    r.raise_for_status()

    print(r.json())


```

list\_customers.php

```

<?php

// list_customers.php

$ch = curl_init("https://tuempresa.factura.com.do/api/v1/customers");

curl_setopt_array($ch, [

  CURLOPT_RETURNTRANSFER => true,

  CURLOPT_HTTPHEADER => ["X-Api-Key: " . getenv("FACTURA_API_KEY")],

]);

$response = curl_exec($ch);

curl_close($ch);

echo $response;


```

## What a 401 looks like

If the key is missing or invalid, the server responds with `401 Unauthorized` and no body. The `ApiKeyFilter` returns `Results.Unauthorized()` and ASP.NET closes the response with `Content-Length: 0`; your client must distinguish this case by the HTTP code, not the body.

401-unauthorized.http

```

HTTP/1.1 401 Unauthorized

Content-Length: 0


```

## Corporativo plan: the 403

REST API access is exclusive to the Corporativo plan. If the key is valid but the workspace is on another plan (or downgraded after issuing it), the routes for documents, notes, expenses, customers, suppliers, certification and signing respond `403 Forbidden` with this body. Catalog routes (products, taxes, currencies, RNC and `*-lookup` queries) currently validate only the key; do not build your integration on that difference.

403-forbidden.http

```

HTTP/1.1 403 Forbidden

Content-Type: application/json


{ "error": "El acceso a la API REST está disponible solo en el plan Corporativo." }


```

## Next steps

Next step 

## Continue here

- [  Quickstart Your first invoice in five minutes. ](/en/desarrolladores/quickstart)
- [  Errors How to handle 400, 401, 403, 404 and 5xx. ](/en/desarrolladores/errores)
- [  Versioning The /api/v1/ policy and change commitment. ](/en/desarrolladores/versionado)
