# Meta

Connectivity, Site information, content types, limits and usage.

Base URL: `https://api.writavo.com/v1`

### GET /ping

Verify a key

- **Operation id**: `ping`
- **Scope**: `none`
- **Permission**: `none`
- **Rate limit class**: read
- **Plan feature**: `none`
- **Spends credits**: no
- **Publishable key may call it**: yes

The cheapest possible authenticated call. Returns the kind of key you presented and the
scopes it carries. Use it to confirm credentials during setup, and as a liveness probe.
It touches no content, so it is exempt from the write rate limit.

**Responses**

| Status | Data | Description |
|---|---|---|
| 200 | object | The key is valid. |
| 401 | - | `INVALID_API_KEY`, `API_KEY_REVOKED` or `API_KEY_EXPIRED`. There is no key, or it is not usable. This response never distinguishes "no such key" from "wrong key", so a caller cannot probe for valid keys. |
| 429 | - | `RATE_LIMIT_EXCEEDED`. Back off and honour `Retry-After`. Limits are per key, per minute, by endpoint class. Writes are limited harder than reads because they cost more to serve, and pipeline runs hardest of all because they cost real money. \| Class \| Endpoints \| Limit \| \|---\|---\|---\| \| read \| every GET \| 600 per minute \| \| write \| POST, PATCH and DELETE on content, taxonomy, keys and webhooks \| 120 per minute \| \| upload \| `POST /media/upload-url` \| 60 per minute \| \| pipeline \| `POST /pipeline/runs` \| 10 per minute \| Every response carries `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset`, so you can slow down before you are refused rather than after. |
| 500 | - | `INTERNAL_ERROR`. Something failed on our side. The message is deliberately generic; the detail is in our logs against the `request_id` in the body, so quote it if you contact support. Safe to retry, and safer still with the same `Idempotency-Key`, which guarantees you do not create a second object if the first request actually succeeded. |
| 503 | - | `MAINTENANCE`. Writes are paused, either platform wide or for your Site. Reads usually keep working, and your published blog is served from cache and stays up. Retry after the window given in `Retry-After`. |

```bash
curl https://api.writavo.com/v1/ping \
  -H "Authorization: Bearer wv_sk_EXAMPLE0000000000000000000000000000"
```

### GET /site

Read Site information

- **Operation id**: `getSite`
- **Scope**: `meta:read`
- **Permission**: `none`
- **Rate limit class**: read
- **Plan feature**: `none`
- **Spends credits**: no
- **Publishable key may call it**: yes

Public facing information about the Site your key belongs to: its display name, the
domain its blog is served from, its locale and its timezone. Scheduling times are
interpreted against this timezone when no offset is supplied.

**Responses**

| Status | Data | Description |
|---|---|---|
| 200 | Site | Site information. |
| 401 | - | `INVALID_API_KEY`, `API_KEY_REVOKED` or `API_KEY_EXPIRED`. There is no key, or it is not usable. This response never distinguishes "no such key" from "wrong key", so a caller cannot probe for valid keys. |
| 403 | - | `INSUFFICIENT_SCOPE`. The key is valid but does not carry the scope this operation requires, or its creator's permissions no longer cover it. This is the **only** 403 in the API. In particular it is never returned for an object belonging to another Site: that case is always 404, so this response never reveals that something exists. |
| 429 | - | `RATE_LIMIT_EXCEEDED`. Back off and honour `Retry-After`. Limits are per key, per minute, by endpoint class. Writes are limited harder than reads because they cost more to serve, and pipeline runs hardest of all because they cost real money. \| Class \| Endpoints \| Limit \| \|---\|---\|---\| \| read \| every GET \| 600 per minute \| \| write \| POST, PATCH and DELETE on content, taxonomy, keys and webhooks \| 120 per minute \| \| upload \| `POST /media/upload-url` \| 60 per minute \| \| pipeline \| `POST /pipeline/runs` \| 10 per minute \| Every response carries `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset`, so you can slow down before you are refused rather than after. |
| 500 | - | `INTERNAL_ERROR`. Something failed on our side. The message is deliberately generic; the detail is in our logs against the `request_id` in the body, so quote it if you contact support. Safe to retry, and safer still with the same `Idempotency-Key`, which guarantees you do not create a second object if the first request actually succeeded. |
| 503 | - | `MAINTENANCE`. Writes are paused, either platform wide or for your Site. Reads usually keep working, and your published blog is served from cache and stays up. Retry after the window given in `Retry-After`. |

```bash
curl https://api.writavo.com/v1/site \
  -H "Authorization: Bearer wv_sk_EXAMPLE0000000000000000000000000000"
```

### GET /content-types

List content types

- **Operation id**: `listContentTypes`
- **Scope**: `meta:read`
- **Permission**: `none`
- **Rate limit class**: read
- **Plan feature**: `none`
- **Spends credits**: no
- **Publishable key may call it**: yes

The article formats available to this Site. A format is an SEO blueprint (How-To,
Listicle, Versus and so on) that shapes how the generator structures an article, and
that you may set on any article via `format_id`.

The list merges the platform defaults with any formats defined for your Site. A Site
format with the same `key` as a platform default overrides it, and only the override is
returned. Formats are read only in v1: defining your own is a dashboard action.

**Responses**

| Status | Data | Description |
|---|---|---|
| 200 | object | The available content types. |
| 401 | - | `INVALID_API_KEY`, `API_KEY_REVOKED` or `API_KEY_EXPIRED`. There is no key, or it is not usable. This response never distinguishes "no such key" from "wrong key", so a caller cannot probe for valid keys. |
| 403 | - | `INSUFFICIENT_SCOPE`. The key is valid but does not carry the scope this operation requires, or its creator's permissions no longer cover it. This is the **only** 403 in the API. In particular it is never returned for an object belonging to another Site: that case is always 404, so this response never reveals that something exists. |
| 429 | - | `RATE_LIMIT_EXCEEDED`. Back off and honour `Retry-After`. Limits are per key, per minute, by endpoint class. Writes are limited harder than reads because they cost more to serve, and pipeline runs hardest of all because they cost real money. \| Class \| Endpoints \| Limit \| \|---\|---\|---\| \| read \| every GET \| 600 per minute \| \| write \| POST, PATCH and DELETE on content, taxonomy, keys and webhooks \| 120 per minute \| \| upload \| `POST /media/upload-url` \| 60 per minute \| \| pipeline \| `POST /pipeline/runs` \| 10 per minute \| Every response carries `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset`, so you can slow down before you are refused rather than after. |
| 500 | - | `INTERNAL_ERROR`. Something failed on our side. The message is deliberately generic; the detail is in our logs against the `request_id` in the body, so quote it if you contact support. Safe to retry, and safer still with the same `Idempotency-Key`, which guarantees you do not create a second object if the first request actually succeeded. |
| 503 | - | `MAINTENANCE`. Writes are paused, either platform wide or for your Site. Reads usually keep working, and your published blog is served from cache and stays up. Retry after the window given in `Retry-After`. |

```bash
curl https://api.writavo.com/v1/content-types \
  -H "Authorization: Bearer wv_sk_EXAMPLE0000000000000000000000000000"
```

### GET /usage

Read plan limits, usage and balances

- **Operation id**: `getUsage`
- **Scope**: `meta:read`
- **Permission**: `none`
- **Rate limit class**: read
- **Plan feature**: `none`
- **Spends credits**: no
- **Publishable key may call it**: no

What your plan allows, what you have used in the current period, and what you can still
spend. Read this before a pipeline run if you want to fail fast rather than handle a
402, and read it after a run to see the balance move.

`credits.balance` is the organisation wide credit balance shared by every Site under the
account. `spend_cap` is this Site's own monthly ceiling and is independent of it: a Site
can be capped while the organisation still has credits, which is the point of a cap.

**Responses**

| Status | Data | Description |
|---|---|---|
| 200 | Usage | Limits, usage and balances. |
| 401 | - | `INVALID_API_KEY`, `API_KEY_REVOKED` or `API_KEY_EXPIRED`. There is no key, or it is not usable. This response never distinguishes "no such key" from "wrong key", so a caller cannot probe for valid keys. |
| 403 | - | `INSUFFICIENT_SCOPE`. The key is valid but does not carry the scope this operation requires, or its creator's permissions no longer cover it. This is the **only** 403 in the API. In particular it is never returned for an object belonging to another Site: that case is always 404, so this response never reveals that something exists. |
| 429 | - | `RATE_LIMIT_EXCEEDED`. Back off and honour `Retry-After`. Limits are per key, per minute, by endpoint class. Writes are limited harder than reads because they cost more to serve, and pipeline runs hardest of all because they cost real money. \| Class \| Endpoints \| Limit \| \|---\|---\|---\| \| read \| every GET \| 600 per minute \| \| write \| POST, PATCH and DELETE on content, taxonomy, keys and webhooks \| 120 per minute \| \| upload \| `POST /media/upload-url` \| 60 per minute \| \| pipeline \| `POST /pipeline/runs` \| 10 per minute \| Every response carries `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset`, so you can slow down before you are refused rather than after. |
| 500 | - | `INTERNAL_ERROR`. Something failed on our side. The message is deliberately generic; the detail is in our logs against the `request_id` in the body, so quote it if you contact support. Safe to retry, and safer still with the same `Idempotency-Key`, which guarantees you do not create a second object if the first request actually succeeded. |
| 503 | - | `MAINTENANCE`. Writes are paused, either platform wide or for your Site. Reads usually keep working, and your published blog is served from cache and stays up. Retry after the window given in `Retry-After`. |

```bash
curl https://api.writavo.com/v1/usage \
  -H "Authorization: Bearer wv_sk_EXAMPLE0000000000000000000000000000"
```
