# Account, keys and billing

> Sign up, read usage and limits, manage API keys and the plan.

Source: https://postwire.io/docs/account/ · Base URL: https://postwire.io · OpenAPI: https://postwire.io/openapi.json

Every limit an account has is readable: `GET /api/usage` gives each one with what is used and what is left. A limit of `null` means unlimited.

- [`POST /api/signup`](#post-api-signup): Create an account (the API key is emailed as a confirmation link, not returned here)
- [`GET /api/me`](#get-api-me): Account info, usage and connections
- [`GET /api/account`](#get-api-account): Alias of GET /api/me: account info, usage and connections
- [`GET /api/usage`](#get-api-usage): This month's posts, today's AI drafts and brands, against the plan's limits
- [`GET /api/plan`](#get-api-plan): The account's plan, what it includes, current usage and the next plan with a checkout link
- [`GET /api/plans`](#get-api-plans): List plans and limits
- [`GET /api/billing`](#get-api-billing): Plan, subscription state and where to manage billing
- [`POST /api/billing/checkout`](#post-api-billing-checkout): Start a Stripe checkout for a paid plan
- [`POST /api/billing/portal`](#post-api-billing-portal): A Stripe customer-portal link to change plan, update the card or cancel
- [`GET /api/keys`](#get-api-keys): List your API keys (prefixes only — the secret is never returned)
- [`POST /api/keys`](#post-api-keys): Create a new API key, optionally with an expiry
- [`DELETE /api/keys/{id}`](#delete-api-keys-id): Revoke an API key immediately

## Create an account (the API key is emailed as a confirmation link, not returned here)

`POST /api/signup`

Signup never returns credentials. We create the account and email a one-time confirmation link; opening it proves you control the mailbox and issues your API key. This prevents anyone from registering an address they do not own and receiving a working key.

No API key needed.

**Body (JSON)**

| Field | Type | Description |
|---|---|---|
| `email` (required) | string (email) |  |

**Responses**

| Status | Means |
|---|---|
| `200` | Account created; pending_verification=true, emailed=true\|false |

```bash
curl -X POST "https://postwire.io/api/signup" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "you@example.com"
}'
```

```js
const res = await fetch("https://postwire.io/api/signup", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    "email": "you@example.com"
  }),
});
console.log(res.status, await res.json());
```

```python
import os, requests

r = requests.post(
    "https://postwire.io/api/signup",
    json={
        "email": "you@example.com",
    },
)
print(r.status_code, r.json())
```

## Account info, usage and connections

`GET /api/me`

limits carries posts_this_month, brands, ai_drafts_today, networks_per_post { limit } and scheduled_queue { used, limit, held, left } (null = no limit). A free account created before the 2-Oct-2026 limits also gets grandfathered { until, note } (it keeps the earlier limits until 2026-11-01). Free accounts get insights_teaser: how many What works patterns are ready and how strong each is, without the answer.

Needs an API key: `Authorization: Bearer pw_live_…`.

**Responses**

| Status | Means |
|---|---|
| `200` | OK |
| `401` | Missing/invalid API key |

```bash
curl "https://postwire.io/api/me" \
  -H "Authorization: Bearer $POSTWIRE_API_KEY"
```

```js
const res = await fetch("https://postwire.io/api/me", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.POSTWIRE_API_KEY}` },
});
console.log(res.status, await res.json());
```

```python
import os, requests

r = requests.get(
    "https://postwire.io/api/me",
    headers={"Authorization": f"Bearer {os.environ['POSTWIRE_API_KEY']}"},
)
print(r.status_code, r.json())
```

## Alias of GET /api/me: account info, usage and connections

`GET /api/account`

Needs an API key: `Authorization: Bearer pw_live_…`.

**Responses**

| Status | Means |
|---|---|
| `200` | Same body as /api/me |
| `401` | Missing/invalid API key |

```bash
curl "https://postwire.io/api/account" \
  -H "Authorization: Bearer $POSTWIRE_API_KEY"
```

```js
const res = await fetch("https://postwire.io/api/account", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.POSTWIRE_API_KEY}` },
});
console.log(res.status, await res.json());
```

```python
import os, requests

r = requests.get(
    "https://postwire.io/api/account",
    headers={"Authorization": f"Bearer {os.environ['POSTWIRE_API_KEY']}"},
)
print(r.status_code, r.json())
```

## This month's posts, today's AI drafts and brands, against the plan's limits

`GET /api/usage`

{ plan, plan_name, period, posts: { used, limit, left, resets_on }, ai_drafts_today: { used, limit, left, resets_at }, brands: { used, limit }, networks_per_post: { limit }, scheduled_queue: { used, limit, held, left }, grandfathered_until?, upgrade? } — a limit of null means unlimited; upgrade appears at 80 % of a limit.

Needs an API key: `Authorization: Bearer pw_live_…`.

**Responses**

| Status | Means |
|---|---|
| `200` | usage |

```bash
curl "https://postwire.io/api/usage" \
  -H "Authorization: Bearer $POSTWIRE_API_KEY"
```

```js
const res = await fetch("https://postwire.io/api/usage", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.POSTWIRE_API_KEY}` },
});
console.log(res.status, await res.json());
```

```python
import os, requests

r = requests.get(
    "https://postwire.io/api/usage",
    headers={"Authorization": f"Bearer {os.environ['POSTWIRE_API_KEY']}"},
)
print(r.status_code, r.json())
```

**Example response**

```json
{
  "plan": "free",
  "plan_name": "Free",
  "period": "2026-10",
  "posts": {
    "used": 6,
    "limit": 20,
    "left": 14,
    "resets_on": "2026-11-01"
  },
  "ai_drafts_today": {
    "used": 1,
    "limit": 5,
    "left": 4
  },
  "brands": {
    "used": 1,
    "limit": 1
  },
  "networks_per_post": {
    "limit": 2
  },
  "scheduled_queue": {
    "used": 2,
    "limit": 3,
    "held": 0,
    "left": 1
  }
}
```

Abridged. `null` as a limit means unlimited.

## The account's plan, what it includes, current usage and the next plan with a checkout link

`GET /api/plan`

Needs an API key: `Authorization: Bearer pw_live_…`.

**Responses**

| Status | Means |
|---|---|
| `200` | { plan, name, price_usd_month, includes, limits: { posts_per_month, brands, ai_drafts_per_day, networks_per_post, scheduled_queue }, usage, grandfathered_until?, next? } |

```bash
curl "https://postwire.io/api/plan" \
  -H "Authorization: Bearer $POSTWIRE_API_KEY"
```

```js
const res = await fetch("https://postwire.io/api/plan", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.POSTWIRE_API_KEY}` },
});
console.log(res.status, await res.json());
```

```python
import os, requests

r = requests.get(
    "https://postwire.io/api/plan",
    headers={"Authorization": f"Bearer {os.environ['POSTWIRE_API_KEY']}"},
)
print(r.status_code, r.json())
```

## List plans and limits

`GET /api/plans`

Each plan: { name, price, brands, limit (posts a month, -1 = unlimited), genDay (AI drafts a day), networksPerPost (-1 = every network in each post), maxQueued (scheduled posts at a time, -1 = unlimited) }.

No API key needed.

**Responses**

| Status | Means |
|---|---|
| `200` | OK |

```bash
curl "https://postwire.io/api/plans"
```

```js
const res = await fetch("https://postwire.io/api/plans", {
  method: "GET",
});
console.log(res.status, await res.json());
```

```python
import os, requests

r = requests.get(
    "https://postwire.io/api/plans",
)
print(r.status_code, r.json())
```

## Plan, subscription state and where to manage billing

`GET /api/billing`

Changing, cancelling or updating a card is done by a person: POST /api/billing/portal returns the portal link.

Needs an API key: `Authorization: Bearer pw_live_…`.

**Responses**

| Status | Means |
|---|---|
| `200` | { plan, name, price_usd_month, subscription: active\|none\|unknown\|null, manage, upgrade, refund } |

```bash
curl "https://postwire.io/api/billing" \
  -H "Authorization: Bearer $POSTWIRE_API_KEY"
```

```js
const res = await fetch("https://postwire.io/api/billing", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.POSTWIRE_API_KEY}` },
});
console.log(res.status, await res.json());
```

```python
import os, requests

r = requests.get(
    "https://postwire.io/api/billing",
    headers={"Authorization": f"Bearer {os.environ['POSTWIRE_API_KEY']}"},
)
print(r.status_code, r.json())
```

## Start a Stripe checkout for a paid plan

`POST /api/billing/checkout`

Needs an API key: `Authorization: Bearer pw_live_…`.

**Body (JSON)**

| Field | Type | Description |
|---|---|---|
| `plan` (required) | string | One of: starter, pro, agency, scale. |

**Responses**

| Status | Means |
|---|---|
| `200` | { url } |

```bash
curl -X POST "https://postwire.io/api/billing/checkout" \
  -H "Authorization: Bearer $POSTWIRE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "plan": "starter"
}'
```

```js
const res = await fetch("https://postwire.io/api/billing/checkout", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.POSTWIRE_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "plan": "starter"
  }),
});
console.log(res.status, await res.json());
```

```python
import os, requests

r = requests.post(
    "https://postwire.io/api/billing/checkout",
    headers={"Authorization": f"Bearer {os.environ['POSTWIRE_API_KEY']}"},
    json={
        "plan": "starter",
    },
)
print(r.status_code, r.json())
```

## A Stripe customer-portal link to change plan, update the card or cancel

`POST /api/billing/portal`

Needs an API key: `Authorization: Bearer pw_live_…`.

**Responses**

| Status | Means |
|---|---|
| `200` | { url } |
| `503` | billing not configured |

```bash
curl -X POST "https://postwire.io/api/billing/portal" \
  -H "Authorization: Bearer $POSTWIRE_API_KEY"
```

```js
const res = await fetch("https://postwire.io/api/billing/portal", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.POSTWIRE_API_KEY}` },
});
console.log(res.status, await res.json());
```

```python
import os, requests

r = requests.post(
    "https://postwire.io/api/billing/portal",
    headers={"Authorization": f"Bearer {os.environ['POSTWIRE_API_KEY']}"},
)
print(r.status_code, r.json())
```

## List your API keys (prefixes only — the secret is never returned)

`GET /api/keys`

Needs an API key: `Authorization: Bearer pw_live_…`.

**Responses**

| Status | Means |
|---|---|
| `200` | keys[] |

```bash
curl "https://postwire.io/api/keys" \
  -H "Authorization: Bearer $POSTWIRE_API_KEY"
```

```js
const res = await fetch("https://postwire.io/api/keys", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.POSTWIRE_API_KEY}` },
});
console.log(res.status, await res.json());
```

```python
import os, requests

r = requests.get(
    "https://postwire.io/api/keys",
    headers={"Authorization": f"Bearer {os.environ['POSTWIRE_API_KEY']}"},
)
print(r.status_code, r.json())
```

## Create a new API key, optionally with an expiry

`POST /api/keys`

Needs an API key: `Authorization: Bearer pw_live_…`.

**Body (JSON)**

| Field | Type | Description |
|---|---|---|
| `name` | string |  |
| `expires_in_days` | integer | 1 to 3650. |

**Responses**

| Status | Means |
|---|---|
| `200` | api_key shown once |

```bash
curl -X POST "https://postwire.io/api/keys" \
  -H "Authorization: Bearer $POSTWIRE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "n8n production",
  "expires_in_days": 365
}'
```

```js
const res = await fetch("https://postwire.io/api/keys", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.POSTWIRE_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "n8n production",
    "expires_in_days": 365
  }),
});
console.log(res.status, await res.json());
```

```python
import os, requests

r = requests.post(
    "https://postwire.io/api/keys",
    headers={"Authorization": f"Bearer {os.environ['POSTWIRE_API_KEY']}"},
    json={
        "name": "n8n production",
        "expires_in_days": 365,
    },
)
print(r.status_code, r.json())
```

## Revoke an API key immediately

`DELETE /api/keys/{id}`

Needs an API key: `Authorization: Bearer pw_live_…`.

**Parameters**

| Field | Type | Description |
|---|---|---|
| `id` (required) | path, string |  |

**Responses**

| Status | Means |
|---|---|
| `200` | revoked |
| `404` | not found or already revoked |

```bash
curl -X DELETE "https://postwire.io/api/keys/7c2a6f0e-5b1d-4c8a-9e3f-2d4b6a8c0e1f" \
  -H "Authorization: Bearer $POSTWIRE_API_KEY"
```

```js
const res = await fetch("https://postwire.io/api/keys/7c2a6f0e-5b1d-4c8a-9e3f-2d4b6a8c0e1f", {
  method: "DELETE",
  headers: { Authorization: `Bearer ${process.env.POSTWIRE_API_KEY}` },
});
console.log(res.status, await res.json());
```

```python
import os, requests

r = requests.delete(
    "https://postwire.io/api/keys/7c2a6f0e-5b1d-4c8a-9e3f-2d4b6a8c0e1f",
    headers={"Authorization": f"Bearer {os.environ['POSTWIRE_API_KEY']}"},
)
print(r.status_code, r.json())
```
