---
title: "Authentication"
description: "Authenticate every request with an API key in the x-api-key header."
---

Every request to `gateway.apinoa.com` carries an API key in the `x-api-key` header. There is no other
way to authenticate, and no request is served without one.

## Get a key

Create a key under **Dashboard > API keys**. The full key is shown **once**, when you create it — copy
it then and store it somewhere safe. If you lose it, create a new one and revoke the old.

You can hold several keys at once, which is how you rotate one without downtime: create the new key,
move your traffic to it, then revoke the old one.

## Send it with every request

```bash
curl -X POST https://gateway.apinoa.com/v1/aliexpress/search \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{ "query": "phone case" }'
```

```javascript
const response = await fetch("https://gateway.apinoa.com/v1/aliexpress/search", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": process.env.APINOA_API_KEY,
  },
  body: JSON.stringify({ query: "phone case" }),
});
```

## Keep it on your server

A key spends your balance. Call the API from your backend and keep the key in a secret store or an
environment variable — never in a browser, a mobile app, or a public repository, where anyone can
read it and bill calls to you.

If a key may have been exposed, revoke it under **Dashboard > API keys**. A revoked key stops working
immediately.

## When authentication fails

| Status | Code | Meaning |
|--------|------|---------|
| 401 | `UNAUTHORIZED` | The `x-api-key` header is missing, or the key is not valid or has been revoked |
| 402 | `INSUFFICIENT_BALANCE` | The key is valid, but your balance does not cover the call |

Each call is charged against your balance at the rate on the [pricing page](/pricing). When the
balance will not cover the next call it returns `402` — retrying does not clear it. Top up under
**Dashboard > Balance**.
