# Team API reference

Use this reference to handle Team API permissions, rate limits, and errors in production.

## Token abilities

Each Team API token has abilities that control which resources it can read or change.

### Read vs write scopes

Abilities are organized into **read** and **write** scopes:

- **Read abilities** (e.g., `read:team`, `read:domains`) allow tokens to view resources and retrieve information
- **Write abilities** (e.g., `write:projects`, `write:webhooks`) allow tokens to create, update, and delete resources

Write abilities do not imply read access. Grant each explicit ability needed by the integration.

The `*` ability grants full access to standard Team API resources. Use explicit read and write abilities instead unless an integration genuinely needs every resource.

`write:member_assignments` is intentionally separate. It can change a member's effective access, so it must be added explicitly by an Owner and requires `read:members`. The `*` ability does not imply it.

### Available abilities

For a complete list of available abilities and their descriptions, see the [Token abilities](/platform/teams/api-tokens#token-abilities) table in the Team API tokens guide.

### Insufficient permissions

If a token attempts an operation without the required ability, the API returns a `403 Forbidden` error:

```json
{
  "error": {
    "code": "FORBIDDEN",
    "message": "This token does not have the required abilities to perform this action."
  }
}
```

:::info
Grant tokens only the abilities they need to perform their intended functions. This principle of least privilege improves security.
:::

## Working with rate limits

The Team API implements rate limiting to ensure fair usage and platform stability. Different rate limits apply based on the operation type.

### Rate limit tiers

- **Read operations**: 300 requests per minute (GET endpoints)
- **Write operations**: 60 requests per minute (POST, PUT, DELETE endpoints)
- **Special endpoints**: 3-10 requests per minute, including project token rotation, DNS verification, webhook tests, and webhook secret regeneration

### Rate limit headers

Every API response includes headers showing your current rate limit status:

```
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 245
X-RateLimit-Reset: 1705843200
```

### Handling rate limit errors

When you exceed the rate limit, the API returns a `429 Too Many Requests` response:

```json
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests. Please try again later.",
    "retry_after": 42
  }
}
```

:::info
Implement exponential backoff when you receive a 429 error. Use the `Retry-After` value when present or the rate-limit reset header to determine when to retry.
:::

## Error handling

The Team API uses standard HTTP status codes to indicate the success or failure of requests.

### Common status codes

| Status | Description |
|--------|-------------|
| **200 OK** | Request succeeded |
| **201 Created** | Resource created successfully |
| **400 Bad Request** | Invalid request format or parameters |
| **401 Unauthorized** | Missing or invalid authentication token |
| **403 Forbidden** | Token lacks required abilities |
| **404 Not Found** | Resource does not exist |
| **409 Conflict** | The requested change conflicts with current resource state or a protected invariant |
| **422 Unprocessable Entity** | Validation error |
| **429 Too Many Requests** | Rate limit exceeded |
| **500 Internal Server Error** | Server error (contact support) |

### Error response format

All error responses follow a consistent format:

```json
{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message"
  }
}
```

### Validation errors

Validation errors (422) include detailed field-level errors:

```json
{
  "message": "The given data was invalid.",
  "errors": {
    "domain": ["The domain has already been taken."],
    "name": ["The name field is required."]
  }
}
```

:::tip
Always check the HTTP status code before parsing response bodies. Log request IDs from headers for troubleshooting with support.
:::

## SDK notes

Official SDKs expose the Team API on the same client you use for sending. Pass a team token, for example `new Lettermint({ teamToken })` in Node.js, `new Lettermint(teamToken: ...)` in PHP, `Lettermint(team_token=...)` in Python, `lettermint.New(lettermint.WithTeamToken(...))` in Go, `Lettermint.builder().teamToken(...).build()` in Java, `new LettermintClient(new LettermintOptions { TeamToken = ... })` in .NET, `Lettermint::builder().team_token(...).build()` in Rust, or `Lettermint.new(team_token: ...)` in Elixir. These clients use bearer authentication and return typed responses where the language supports it.

- Pass pagination and filter values as query parameters, for example `page[size]`, `page[cursor]`, or `filter[search]`.
- Message `source`, `html`, and `text` endpoints return raw strings instead of JSON response objects.
- Use Project API tokens only with the Sending API. Team API clients require Team API tokens.

## Next steps

- **[Manage member access](/platform/teams/team-api/member-access)** - Assign roles and project access from an integration
- **[Team API workflows](/platform/teams/team-api/use-cases)** - Review common workflows and production guidance
- **[API reference](/api-reference/team)** - View complete Team API documentation
