# API keys

> Secret keys for servers, publishable keys for browsers locked to allowed origins, and how to send a key to api.geolith.app.

Create keys in the dashboard at [console.geolith.app](https://console.geolith.app). A key belongs to a project; usage counts against your account's plan.

## Two kinds of key

| Kind | Prefix | Where | Origin check |
| --- | --- | --- | --- |
| Secret | `gc_sk_` | Servers, scripts, AI agent tools | None, unless you list origins on the key |
| Publishable | `gc_pk_` | Web pages | Required: only the origins listed on the key are answered |

A publishable key with no allowed origins answers nothing. The origin is read from the `Origin` header, else from `Referer`. A request with a publishable key and neither header gets `403 origin_not_allowed`. Browsers send them on `fetch` calls and map tile requests, so this works with no extra code.

Never put a secret key in browser code, a mobile app bundle or a public repository. Revoke a leaked key in the dashboard; revocation takes effect within a minute.

## Sending the key

Either form works. When both are present, the header wins.

```bash
# Header (recommended on servers: keeps the key out of URLs and logs)
curl -H "Authorization: Bearer YOUR_API_KEY" "https://api.geolith.app/v1/search?text=pune"

# Query parameter (simplest in browsers and map tile URLs)
curl "https://api.geolith.app/v1/search?text=pune&api_key=YOUR_API_KEY"
```

## Allowed origins

List each origin as scheme, host and port, for example `https://shop.example.com` or `http://localhost:5173`. Add your development origin to a separate publishable key rather than to the production key.

## Errors

| Status | Code | Meaning |
| --- | --- | --- |
| 401 | `missing_api_key` | No key on the request |
| 401 | `invalid_api_key` | Malformed, unknown or revoked key |
| 403 | `origin_not_allowed` | Publishable key used from an origin it does not list, or with no `Origin` or `Referer` |

See [Quotas and errors](/search/hosted/quotas-and-errors) for every status.
