# API basics (/docs/api)



Base URL [#base-url]

```
https://feedhorizon.com/api/v1
```

The version is part of the path. Changes inside `v1` only add things: new endpoints, new optional fields, new values in lists such as webhook events. Your code should ignore fields it does not know. Every change is listed in the [Changelog](/docs/changelog).

Requests [#requests]

* Send your API key as `Authorization: Bearer fh_…`, see [Authentication](/docs/api/authentication).
* Send bodies as JSON with `Content-Type: application/json`.
* Send an `Idempotency-Key` header on `POST` requests that create something, so a retry after a dropped connection does not create it twice, see [Idempotency](/docs/api/idempotency).

Responses [#responses]

A single object comes wrapped in `data`:

```json
{ "data": { "id": "post_0195f0a27b3c7d4e8f5a1b2c3d4e5f60", "status": "scheduled" } }
```

A list has `data` and `nextCursor`, see [Pagination](/docs/api/pagination):

```json
{ "data": [ { "id": "post_…" } ], "nextCursor": null }
```

A delete answers `{ "data": { "id": "…", "deleted": true } }`. An error answers with `error` and a 4xx or 5xx status, always in the same shape, see [Errors](/docs/api/errors).

Every response carries an `x-request-id` header. Quote it when you contact support.

Ids [#ids]

Ids carry a prefix that says what they belong to, followed by 32 hexadecimal characters:

| Prefix  | Object                                 |
| ------- | -------------------------------------- |
| `org_`  | Organization                           |
| `prof_` | Profile                                |
| `acc_`  | Connected account                      |
| `post_` | Post                                   |
| `tgt_`  | One account of a post (`targets[].id`) |
| `med_`  | Media file                             |
| `wh_`   | Webhook                                |
| `key_`  | API key                                |
| `inv_`  | Connect link                           |

Pass ids exactly as you received them. An id of the wrong kind, such as an account id in `profileId`, fails with a message that names both kinds. [Data model](/docs/concepts/data-model) shows how the objects relate.

A profile can carry your own `externalId` (for example your customer id). It is unique per organization, so `GET /profiles?externalId=…` finds the profile of a customer without storing our id.

Timestamps and time zones [#timestamps-and-time-zones]

All timestamps are ISO 8601. Responses use UTC (`2026-11-10T11:00:00.000Z`). In requests, include an offset (`2026-11-10T12:00:00+01:00`) or a `Z`. Time zones are IANA names such as `Europe/Berlin`; each profile has one, and the queue works in it. See [Scheduling](/docs/guides/scheduling#time-zones).

Limits [#limits]

Requests are limited per API key and minute, by plan. Every response tells you how many are left, see [Rate limits](/docs/api/rate-limits).

OpenAPI [#openapi]

The reference pages in this section are generated from the same code that serves the API, so they always match it. The OpenAPI 3.1 file is at [/openapi.json](/openapi.json): import it into Postman, Insomnia or a client generator.
