# API keys

Creating a key, the one chance you get to copy it, revoking one, and webhook endpoints

Section: app. Audience: public. Updated: 2026-10-09.

---
API keys let your own systems talk to Horizon. They are under **"Settings"**, in **"API keys & webhooks"**, on the **"API keys"** card. Until September 2026 that card was part of the security section.

This page covers the screen. For what to do with a key once you have one, see the [API overview](/api/), and for rotation, what a key can and cannot reach, and how to keep keys safe, see [Authentication and keys](/api/authentication/).

The section is for the account owner only, and the platform refuses these requests for anyone else regardless of what the interface shows.

## Creating one

Type a name in **"Key name (optional)"** and press **"Create key"**. Leave the name empty and the key is called **"New API Key"**, which is worth avoiding.

Name it for what will use it, not for who made it. A key called "integration" tells nobody anything six months later, and you cannot read a key's value to work out where it went.

## Copy it now

**This is the important part.** The full key is never displayed. Right after you create it, the new key's card has a **"Copy"** button that copies the full key to your clipboard, and the app says **"API key generated. Copy it now; it will be hidden afterwards."** Copy it then, and paste it straight into wherever it will be stored.

The button lasts about a minute, and only while you stay on the page. After that, and on every later visit, the card shows only a short masked preview, enough to tell keys apart in the list and no use as a credential. The copy control disappears with the value, because copying a mask would be worse than useless.

Each card also shows the date the key was created and the date it was last used, or **"Never"** for a key nothing has used yet. A last-used date that stops changing is how you tell that nothing uses a key any more.

If you lose a key, you cannot recover it. Create a new one, move whatever was using the old one across, and revoke the old one.

## Revoking

**"Revoke"** on a key ends it. There is no confirmation step and no undo: anything using it stops working on its next request, so make sure you know what that is first.

Revoke a key whenever you cannot account for it, when the person or system that used it has gone, or when it may have been exposed. A key you are unsure about is a key to revoke.

## If you have none

The card says **"No API keys yet"** with **"Create one to start integrating."** That is the expected state for an account that has not integrated anything.

## What a key can do with orders

A key can read orders and create new ones. It cannot change or delete an order, buy its label or upload orders from a file: those can spend money or reach your customers and your stores, so they stay in the app. The full list is in [Authentication and keys](/api/authentication/).

When a key creates an order, some fields are Horizon's own and are refused:

| Fields | Why |
|---|---|
| `owner`, `label_automation`, `address_check`, `shipping_overrides`, `shopify_order_id`, `shop_id`, `checkout_method`, `customer_locale` | Written by Horizon: the account, what the label automation did, the address check's record, what the automation rules decided for the label, the Shopify identity, and the checkout method and customer language a store's import sets |

An order that sets one of them is answered 400 with `error_code` `READ_ONLY_FIELDS`, the list of the refused fields in `read_only_fields`, and a reason under each field's name. Nothing is saved. Computed keys of the answer (`id`, `created_at`, `carrier_shipment`, `address_check_summary`, `fulfillments`, `shipments`) are ignored when sent.

The ship-to fields (`recipient_name`, `company`, `address1`, `address2`, `city`, `postal_code`, `province_code`, `province_name`, `country`, `phone`, `order_phone`) are checked for the destination country's format. A value that fails is answered 400 with `error_code` `ADDRESS_INVALID`, a message under each field's name and, in `fields`, a code per field: `REQUIRED`, `COUNTRY_INVALID`, `POSTCODE_INVALID_FORMAT` (with `examples`), `PHONE_INVALID` or `TOO_LONG` (with `max`). Whether the street exists is left to the address check, which runs on the new order as on any other. See [Address checks](/app/address-checks).

## Webhook endpoints

**"Webhook endpoints"** is where you register addresses for Horizon to notify when things happen, choosing which events each one receives. When there are none, the card says **"No webhook endpoints configured"** rather than showing an empty box.

An address that is wrong is validated in the form before it is saved.

When you add an endpoint, its card shows its **signing secret** once. Copy it before you choose **"Done"** or leave the page: Horizon never shows it again. Your server uses it to check that each delivery really came from Horizon. To get a new secret, delete the endpoint and add it again. The events, what each delivery contains and how to check the signature are in [Webhooks](/api/webhooks/).

A webhook whose last delivery failed shows it on its card, and puts a dot on **"API keys & webhooks"** in the settings list.

## Related

Your password, two-step verification and sessions stay in **"Security"**. See [Security](/app/security).

Nothing an API key can do spends money: see [Authentication and keys](/api/authentication/) for what a key can and cannot do.