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

# Peeps API

> Base URL, authentication, rate limits and errors of the Peeps API, which your harness or CI job calls over HTTP with an organization API key.

The Peeps API lets your own systems call Peeps over plain HTTP with an [API key](/api-reference/api-keys). Nobody signs in and no coding agent runs. Today the API sends test report files to Peeps, checks on their uploads and describes the key you call it with.

## Endpoints

> **[Send a report file](/api-reference/results/send-a-report-file)**
>
> `PUT /projects/{project}/results/{fileName}`

> **[Get an upload](/api-reference/results/get-an-upload)**
>
> `GET /results/uploads/{uploadId}`

> **[Get the current key](/api-reference/api-key/get-the-current-key)**
>
> `GET /api-key`

For a walkthrough with curl and Python, see [Send results from your harness](/results-api/send-results).

## Base URL

```text theme={null}
https://app.peepsai.com/api/v1
```

## Authentication

Send your [API key](/api-reference/api-keys) on every request:

```text theme={null}
Authorization: Bearer peeps_…
```

## Responses

Every response carries the header `Peeps-Results-Api: 1`. A refusal has a JSON body with a code you can act on and a message you can show:

```json theme={null}
{
  "error": {
    "code": "release_required",
    "message": "This project has no current release. Send ?release=<label> with the file."
  }
}
```

## Rate limits

| What | Limit |
| - | - |
| Sends per key | 30 a minute |
| Sends per organization, across all its keys | 60 a minute |
| Upload and key checks per key | 120 a minute, shared |

Over a limit, Peeps answers `429 rate_limited`. Wait the number of seconds in the `Retry-After` header.

## Errors

| Status | Code | When | What to do |
| - | - | - | - |
| `400` | `invalid_request` | `Content-Length` isn't a number, the file is empty, the body isn't the size `Content-Length` says, or the `Idempotency-Key` isn't 1 to 200 printable ASCII characters. | Fix the request and send it again. |
| `400` | `invalid_release` | `release` isn't a valid release name. | Use 1 to 80 letters, digits, spaces and `. _ + - ( )`, starting with a letter or digit. |
| `400` | `invalid_file_name` | The file name is over 255 characters, holds a `/`, `\` or control character, or doesn't end in `.xml` or `.html`. | Send a plain file name ending in `.xml` or `.html`, URL-encoded. |
| `401` | `unauthenticated` | The key is missing, malformed, unknown, revoked or expired, or API keys are turned off for your organization. Peeps doesn't say which. | Check the `Authorization` header and the key's status on the **API keys** page. |
| `404` | `not_found_or_no_access` | No project has that acronym or ID in your organization, or the key can't send to it. When checking an upload: this key sent no upload with that ID. | Check the project and the key's projects. Check the upload ID. |
| `408` | `body_timeout` | The file didn't arrive within 120 seconds. | Send it again. |
| `409` | `idempotency_mismatch` | This `Idempotency-Key` was used in the last 24 hours with a different project, file name, file or `release`. | Use a new `Idempotency-Key` for this file. |
| `409` | `upload_closed` | The upload closed before the file was stored. | Send the file again. If you set an `Idempotency-Key`, use a new one. |
| `411` | `length_required` | The request has no `Content-Length` header. | Send the file with its size, as `curl -T` does. |
| `413` | `too_large` | The file is over 50 MiB. | Send a smaller report file. |
| `422` | `release_required` | You left out `release` and the project has no current release. | Add `?release=`, or set the project's **Current release**. |
| `422` | `unsupported_format` | The file is neither a JUnit XML nor a pytest-html report, whatever its name. Peeps stores none of it. | Send the report file your test run wrote. |
| `422` | `pytest_html_v3` | The file is a pytest-html 3 report. Peeps stores none of it. | Run `pip install -U 'pytest-html>=4'`, or send the JUnit XML. |
| `422` | `platform_not_supported` | The project isn't a web project, or its tests live in a GitHub repository. | Send results to a web project whose tests aren't in a GitHub repository. |
| `429` | `rate_limited` | The key or your organization reached its limit for this minute. | Wait the number of seconds in `Retry-After`, then send again. |
| `503` | `busy` | Peeps is receiving many files at once (`Retry-After: 5`), or your organization's API keys already have six uploads being received or processed (`Retry-After: 60`). | Wait the number of seconds in `Retry-After`, then send the file again. |
| `503` | `results_unavailable` | Peeps can't file results right now. | Try again later. |
| `500` | `internal` | Something went wrong in Peeps. | Send the request again. It's safe to resend. |

Each endpoint page lists the errors that endpoint can return.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.