---
title: "Errors"
description: "How the Pallyy API reports errors: HTTP status codes, the machine-readable error code in the response body, and validation error details."
category: "getting-started"
emoji: "⚠️"
order: 3
datePublished: "2026-08-20"
dateUpdated: "2026-08-20"
---

The Pallyy API uses conventional HTTP status codes and returns a JSON body with a human-readable message. Most errors also carry a machine-readable code in `data.code`, plus extra fields describing the problem.

```json
{
  "statusCode": 403,
  "statusMessage": "This API key is missing the required scope: post-sets:write.",
  "data": {
    "code": "api-key:missing_scope"
  }
}
```

## Status codes

| Status | Meaning |
| --- | --- |
| `400` | Invalid request: the body or query failed validation, or the input references something it cannot use |
| `401` | Missing, invalid, disabled, or revoked API key |
| `403` | The key is missing a required scope, or the account's plan does not allow the action |
| `404` | The resource does not exist, is not yours, or is outside the key's social set restriction |
| `409` | Conflict with an existing resource, `data.conflictId` points at it |
| `412` | A precondition has failed, for example a post set that is publishing or published that cannot be modified |
| `429` | Rate limit exceeded, see [rate limits](/docs/api/rate-limits) |

## Error codes

| Code | Status | Meaning |
| --- | --- | --- |
| `api-key:invalid` | 401 | The key is invalid, disabled, or revoked |
| `api-key:missing_scope` | 403 | The key is missing the scope the endpoint requires |
| `not_found` | 404 | The resource was not found |
| `rate_limit_exceeded` | 429 | Too many requests, includes `count` and `max` |
| `conflict` | 409 | A duplicate exists, includes `conflictId` |
| `post-set:invalid_posts` | 400 | One or more posts failed validation, includes an `errors` array |
| `post-set:monthly_posts_exceeded` | 403 | The plan's monthly post limit would be exceeded, includes `used`, `planned`, and `max` |
| `post-set:carousels_not_available` | 403 | The plan does not allow carousel posts |
| `post-set:videos_not_available` | 403 | The plan does not allow video posts |
| `post-set:repeats_not_available` | 403 | The plan does not allow repeating posts |
| `post-set:media_not_found` | 400 | A referenced media item was not found, includes the id |
| `post-set:media_social_set_mismatch` | 400 | A referenced media item belongs to a different social set |
| `post-set:duplicate_references` | 400 | The same post or media id is referenced more than once, includes `ids` |
| `post-set:post_not_found` | 400 | An update references a post id that is not part of the set |
| `post-set:post_account_type_mismatch` | 400 | An update tries to change a post's account type |
| `post-set:repeat_not_updatable` | 400 | The repeat rule of a set that already belongs to a series cannot change |
| `post-set:read_only` | 412 | The post set is publishing or published and can no longer be edited |
| `media-upload:pending_exceeded` | 400 | Too many pending media uploads for the social set, includes `count` and `max` |
| `media-upload:unavailable_upload_bytes` | 400 | The file exceeds the plan's remaining monthly upload allowance, includes `avail` |
| `media-upload:unavailable_storage` | 400 | The file exceeds the plan's remaining storage, includes `avail` |

## Validation errors

Requests whose body or query does not match the endpoint's schema return a `400` where `statusMessage` describes the first violation and `data` is an array of every violation found.

Post content that is structurally valid but cannot be scheduled, for example a caption over the network's limit or an Instagram post with no media, returns `post-set:invalid_posts` with one entry per problem:

```json
{
  "statusCode": 400,
  "statusMessage": "Post-set cannot be scheduled since posts are invalid",
  "data": {
    "code": "post-set:invalid_posts",
    "errors": [
      { "index": 0, "accountType": "INSTAGRAM", "message": "Instagram posts require at least one media item" }
    ]
  }
}
```
