# Responses and errors

> The envelope of every response, the errors array that always comes back, the HTTP status codes and what to do with each, validation and business messages, the language of messages and deleted items.

Every API response comes in the same envelope. That lets a single handler serve every call.

## Success

```json
{
  "success": true,
  "message": "Login successful.",
  "data": { },
  "pagination": { "page": 1, "limit": 20, "total": 137, "totalPages": 7 }
}
```

`pagination` only appears in lists. See [Pagination](/api/paginacao).

## Error

```json
{
  "success": false,
  "message": "Valid email is required",
  "errors": [{ "param": "email", "message": "Valid email is required" }]
}
```

- The `errors` array **always** comes back, even with a single error.
- `param` says which field caused the error, when there is one.
- `message` is the message to show.

This way, validation and business rules are handled the same way: show `errors[].message` next to the `param` field; without a `param`, show it at the top.

## The two kinds of error

| Kind | Example | How to recognize it |
|---|---|---|
| **Validation** | A field missing or in the wrong format | `400`, `param` = the field, a short message (*"Title is required"*) |
| **Business rule** | An action the current state doesn't allow | `400`, `403`, `404` or `409`, a message that explains (*"Insufficient balance…"*) |

## Status codes

| Code | Means | What to do |
|---|---|---|
| `200` / `201` | It worked (`201` when something is created) | — |
| `204` | It worked, no body (deletions) | — |
| `400` | Validation failed, or `X-CommunityId` is missing (`errors[0].param = "X-CommunityId"`) | Read `errors` and fix it |
| `401` | Token missing, invalid or expired | Sign in again |
| `402` | The payment was declined | Show the message to the buyer |
| `403` | No permission: insufficient role, or the space restricts who can create | Check the role and the `X-CommunityId` |
| `404` | Doesn't exist, was deleted, belongs to another community, or the path is one of the old ones with `/communities/{communityId}/` | Check the id, the community and the [path](/api/x-community-id#the-paths-that-changed) |
| `409` | Conflict with the current state | Read the message |
| `429` | Too many attempts (e.g. 10 invalid coupon codes in 15 minutes) | Wait a few minutes |
| `500` | Internal error | Try again; if it persists, write to support |

## Real examples

| Situation | Response |
|---|---|
| Listing products without the `X-CommunityId` header | `400` · *Send the community in the X-CommunityId header.*, with `param: "X-CommunityId"` |
| Creating a space in a section that doesn't exist | `400` · *Seção não encontrada ou não pertence a esta comunidade.* (section not found or not in this community) |
| Creating a course module in a course that doesn't exist | `404` · *Curso não encontrado.* (course not found) |
| A member posting in a "Staff" space | `403` · *Only staff members (admin, owner, moderator) can perform this action* |
| An admin changing an owner | `403` · *Only an owner or a SuperAdmin can remove, demote or change an owner.* |
| Taking an add-on with subscribers off a plan | `409` · *This add-on cannot be taken off the plan…* |

More examples, in the order you run into them while building something, in [Creation order](/api/ordem-de-criacao).

## Language of messages

Messages come in the language of the `Accept-Language` header (`pt-BR`, `en-US`, `es-ES`, `it-IT`, `de-DE` and the other variants). Some format validations still answer in English.

## Item from another community

An item that belongs to another community answers **404**, the same as an id that doesn't exist. The API doesn't reveal that the item exists elsewhere: for the caller, it doesn't exist in the `X-CommunityId` community.

| When | Response |
|---|---|
| The route names a space from another community (`?spaceId=`, the space of a course or a call for papers) | `404` · `space.notFound` (*Space not found*) |
| The route names an item from another community (reading a post, its comments, an event's participants) | `404` · `common.notFound` (*Not found*) |
| Editing, deleting, commenting on, reacting to or pinning content, an event or a status from another community | `404` · the module's message (`content.notFound`, `event.notFound`, `status.notFound`, `course.notFound`) |

Being an owner, admin or moderator in one community gives no access to anything in another, even when sending your own community's header. If the item is from the community and still answers 404, check that `X-CommunityId` is the right community.

## Deleted items

The API doesn't truly delete: deleted items are marked as removed and stop showing up. That's why a deleted id answers **404**, as if it never existed.

## With the SDK

The SDK throws a `MemberfyError` with `.status`, `.body` (the whole envelope) and `.errors`. See [JavaScript SDK](/api/sdk-js).

## Related

- [Authentication](/api/autenticacao)
- [X-CommunityId](/api/x-community-id)
- [Creation order](/api/ordem-de-criacao)
