> ## Documentation Index
> Fetch the complete documentation index at: https://docs.genviral.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Response Pattern

> Consistent JSON response envelope and error handling for the Genviral social media posting API. Every endpoint - TikTok, Instagram, YouTube, Pinterest, LinkedIn, Facebook - returns the same typed structure for easy parsing by AI agents and automation scripts.

> Understanding responses, error handling, and status codes for every Partner API endpoint. Designed for easy parsing by OpenClaw agents, Claude Code, and any programmatic integration.

## Envelope Structure

All endpoints return the same typed envelope so you can branch on `ok` once and stay type-safe everywhere else.

<ResponseField name="ok" type="boolean" required>
  Indicates success (`true`) or failure (`false`).
</ResponseField>

<ResponseField name="code" type="number" required>
  Mirrors the HTTP status code returned by the endpoint.
</ResponseField>

<ResponseField name="message" type="string" required>
  Human-readable context for logs or UI surfaces.
</ResponseField>

<ResponseField name="data" type="object">
  Present only when `ok` is `true`. Contains the payload documented for each endpoint.
</ResponseField>

<ResponseField name="error_code" type="string">
  Optional machine-friendly identifier for failures (e.g., `invalid_token`,
  `subscription_required`).
</ResponseField>

```json theme={null}
{
  "ok": true,
  "code": 200,
  "message": "Accounts retrieved",
  "data": { "...": "..." }
}
```

```json theme={null}
{
  "ok": false,
  "code": 401,
  "message": "API key not found",
  "error_code": "invalid_token"
}
```

<Note>
  When `ok` is `true`, `data` is guaranteed to exist. When `ok` is `false`, `data` is omitted, so
  you can rely on that distinction for strict typing in TypeScript, Swift, or Go clients.
</Note>

## Sample Handling

```ts theme={null}
const res = await fetch('https://www.genviral.io/api/partner/v1/accounts', {
  headers: { Authorization: `Bearer ${process.env.GENVIRAL_TOKEN}` },
});
const payload = await res.json();

if (!payload.ok) {
  throw new Error(`Genviral error ${payload.code} – ${payload.message}`);
}

payload.data.accounts.forEach((account: any) => {
  console.log(account.id, account.type, account.platform);
});
```

```python theme={null}
response = requests.get(
    "https://www.genviral.io/api/partner/v1/posts",
    headers={"Authorization": f"Bearer {GENVIRAL_TOKEN}"}
)
data = response.json()

if data["ok"]:
    print(data["data"]["summary"])
else:
    raise RuntimeError(f"Genviral error {data['code']}: {data['message']}")
```

## Common Status Codes

| Code  | Meaning               | Notes                                                                                                                                                                                                                                                        |
| ----- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `200` | Success               | Returned for GET/PATCH requests, `POST /posts/retry`, and idempotent `POST /posts` replays that return an existing post instead of creating a new one.                                                                                                       |
| `201` | Created               | Returned by fresh create-style requests such as `POST /posts`, `POST /slideshows/generate`, `POST /packs`, `POST /packs/:pack_id/images`, `POST /templates`, `POST /templates/from-slideshow/:slideshow_id`, and `POST /slideshows/:slideshow_id/duplicate`. |
| `202` | Accepted              | Returned for async-start endpoints such as `POST /studio/videos/generate`.                                                                                                                                                                                   |
| `400` | Bad Request           | Missing/invalid parameters, unreachable media URLs, etc.                                                                                                                                                                                                     |
| `401` | Unauthorized          | API key missing, malformed, or revoked.                                                                                                                                                                                                                      |
| `402` | Subscription Required | Active Creator, Professional, or Business subscription is required.                                                                                                                                                                                          |
| `403` | Forbidden             | Tier or scope denied (e.g., `tier_not_allowed` for Scheduler).                                                                                                                                                                                               |
| `404` | Not Found             | Resource doesn’t exist in the authenticated key scope.                                                                                                                                                                                                       |
| `422` | Unprocessable Entity  | JSON body parsed but failed schema validation (invalid payload).                                                                                                                                                                                             |
| `429` | Too Many Requests     | Back off-respect concurrency guidance (3–10 requests at a time).                                                                                                                                                                                             |
| `500` | Internal Server Error | Rare; retry with exponential backoff and contact support if needed.                                                                                                                                                                                          |

<Tip>
  `error_code` is the fastest way to branch on known issues (e.g., `invalid_media_url`,
  `post_not_mutable`). Log both `code` and `error_code` for observability.
</Tip>

## Handling `422 invalid_payload`

When payload validation fails at the schema/shape layer, Partner API returns `422` with schema-level and field-level details. Account-aware rules that require resolved account metadata (for example a caption that is valid for Facebook but too long for a selected Pinterest account, or a text-only post sent to TikTok) surface later as `400 validation_failed`. Unknown provider keys under `settings` are rejected here because Partner API fails closed on unrecognized platform settings.

```json theme={null}
{
  "ok": false,
  "code": 422,
  "message": "Invalid payload",
  "error_code": "invalid_payload",
  "issues": {
    "formErrors": [],
    "fieldErrors": {
      "settings": ["Unrecognized key(s) in object: 'mastodon'"],
      "caption": ["String must contain at most 63206 character(s)"],
      "accounts": ["Expected object, received string"]
    }
  }
}
```

Recommended handling:

1. Detect `code === 422` and `error_code === "invalid_payload"`.
2. Read both `issues.formErrors` and `issues.fieldErrors`.
3. Fix field shape/data and retry.
4. Do not retry unchanged payloads.

```ts theme={null}
if (!payload.ok && payload.code === 422 && payload.error_code === 'invalid_payload') {
  const formErrors = payload.issues?.formErrors ?? [];
  const fieldErrors = payload.issues?.fieldErrors ?? {};
  console.error('Invalid payload', { formErrors, fieldErrors });
  throw new Error('Fix payload shape before retrying');
}
```
