# Payload


## Endpoint

`POST https://ingress.flareapp.io/v1/errors`

### Headers

| Header | Value | Description                                                                  |
  |---|---|------------------------------------------------------------------------------|
| `Content-Type` | `application/json` | Required                                                                     |
| `Accept` | `application/json` | Required                                                                     |
| `x-api-token` | `{apiToken}` | API token                                                                    |
| `X-Report-Browser-Extension-Errors` | `true` | Optional, omit this header to filter out errors caused by browser extensions |

## Authentication

Authenticate using your project's API key in the `x-api-token` header. Both the private and public API key can be used for this endpoint.

## Payload

| Field | Type | Validation | Description |
  |---|---|---|---|
| `exceptionClass` | string/null | nullable | Exception class name |
| `seenAtUnixNano` | int | required | Unix timestamp in nanoseconds |
| `message` | string/null | nullable | Error message |
| `code` | string/null | nullable, max 64 | Exception code |
| `applicationPath` | string/null | nullable | App root path |
| `openFrameIndex` | int/null | nullable | Index of the stack frame to focus on |
| `sourcemapVersionId` | string/null | nullable | Source map version ID for JS source map resolution |
| `attributes` | object | required | Flat key-value context data (see [Attributes](/docs/protocol/errors/attributes)) |
| `events` | array | required | Spans and span events |
| `stacktrace` | array | required | Array of stack frame objects |
| `trackingUuid` | string/null | nullable, uuid | Unique report identifier |
| `handled` | bool/null | nullable | Whether the exception was caught |
| `overriddenGrouping` | enum/null | nullable | Custom grouping strategy (overrides the default) |

#### `overriddenGrouping` Values

By default, Flare groups errors by exception class and the top application frame in the stacktrace. Set `overriddenGrouping` to override this with a different strategy:

| Value | Description |
  |---|---|
| `exception_class` | Group by exception class only |
| `exception_message` | Group by exception message only |
| `exception_message_and_class` | Group by both message and class |
| `full_stacktrace_and_exception_class_and_code` | Group by full stacktrace, class, and code |

### Events

Spans and span events are combined into a single `events` array on the root payload. Spans represent operations with a duration (e.g. a query or HTTP request) and have both a start and end time. Span events represent point-in-time occurrences (e.g. a log entry or cache hit) and only have a start time, `endTimeUnixNano` is always `null`. For the full list of types and their attributes, see [Events](/docs/protocol/general/events).

| Field | Type | Description |
|---|---|---|
| `startTimeUnixNano` | int | Start time in nanoseconds |
| `endTimeUnixNano` | int/null | End time in nanoseconds. `null` for span events |
| `type` | string | Type identifier |
| `attributes` | object | Flat key-value attributes |

### Stacktrace Frames

| Field | Type | Validation | Description |                                                                                                                                                                        
  |---|---|---|---|                                                                                                                                                                                                  
| `file` | string | required | File path |                                                                                                                                                                         
| `lineNumber` | int | required | Line number |                                                                                                                                                                    
| `columnNumber` | int | optional | Column number (useful for JS) |                                                                                                                                                
| `method` | string/null | nullable | Method/function name |                                                                                                                                                       
| `class` | string/null | nullable | Class name |                                                                                                                                                                  
| `codeSnippet` | `object<int, string>`/null | nullable | Code lines keyed by line number |                                                                                                                        
| `arguments` | array/null | nullable | Array of argument objects (null if not collected) |
| `isApplicationFrame` | bool | optional | Whether this is application code (vs vendor) |

#### Arguments

Each entry in the `arguments` array:

| Field | Type | Description |
  |---|---|---|
| `name` | string | Parameter name (e.g. `$userId`, `request`). Falls back to `arg0`, `arg1`, etc. when reflection is unavailable. |
| `value` | mixed | A serializable representation of the argument value (see below) |
| `original_type` | string | The original type name before reduction (e.g. `int`, `array`, `User`) |
| `passed_by_reference` | bool | Whether the parameter is passed by reference |
| `is_variadic` | bool | Whether the parameter is variadic |
| `truncated` | bool | Whether the value was truncated |

##### Argument value Reduction Guidelines

Arguments must be reduced to JSON-serializable values before sending. The exact reduction strategy is up to the implementer, but the following guidelines should be followed:

- Primitive values (int, float, bool, string, null) should be kept as-is.
- Large arrays should be truncated to a reasonable size (e.g. 25 items) and `truncated` set to `true`.
- Nested arrays should be recursively reduced.
- Objects that cannot be safely serialized should be reduced to a string representation, with the original type stored in `original_type`.
- Sensitive values (passwords, tokens, secrets) should never be sent. Replace them with a placeholder string.
- Closures and callbacks should be reduced to their source location if possible.
- Keep the total payload size in mind. Argument data is one of the first things trimmed when the payload exceeds the size limit.

## Responses

All responses include CORS headers (`Access-Control-Allow-Origin: *`) and return `application/json`.

| Status | Description |
|---|---|
| `201` | Error report accepted |
| `401` | Missing API key |
| `403` | Invalid API key |
| `405` | HTTP method not allowed (only `POST` is accepted) |
| `429` | Rate limit or error quota exceeded |

All error responses follow this structure:

```json
{
    "message": "Description of the error",
    "errors": {}
}
```

## Example

```json
{
    "exceptionClass": "Illuminate\\Database\\QueryException",
    "seenAtUnixNano": 1710252000000000000,
    "message": "SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'customer@example.com' for key 'orders_email_unique' (Connection: mysql, SQL: insert into `orders` (`email`) values (customer@example.com))",
    "code": "23000",
    "applicationPath": "/var/www/app",
    "openFrameIndex": 0,
    "sourcemapVersionId": null,
    "trackingUuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "handled": false,
    "overriddenGrouping": null,
    "attributes": {
        "service.name": "My Application",
        "service.version": "1.0.0",
        "service.stage": "production",
        "telemetry.sdk.language": "PHP",
        "telemetry.sdk.name": "spatie/flare-client-php",
        "telemetry.sdk.version": "1.0.0",
        "flare.language.name": "PHP",
        "flare.language.version": "8.4.0",
        "flare.framework.name": "Laravel",
        "flare.framework.version": "12.0.0",
        "flare.exception.db_statement": "insert into `orders` (`email`) values (?)",
        "flare.exception.db_system": "mysql",
        "host.name": "web-01",
        "host.arch": "arm64",
        "os.type": "linux",
        "os.name": "Ubuntu",
        "git.hash": "abc123",
        "git.branch": "main",
        "flare.entry_point.type": "web",
        "flare.entry_point.value": "https://example.com/checkout",
        "flare.entry_point.handler.identifier": "GET /checkout",
        "flare.entry_point.handler.name": "App\\Http\\Controllers\\CheckoutController",
        "flare.entry_point.handler.type": "laravel_controller",
        "url.full": "https://example.com/checkout",
        "url.scheme": "https",
        "url.path": "/checkout",
        "http.request.method": "POST",
        "http.route": "checkout",
        "http.request.body.size": 256,
        "client.address": "192.168.1.1",
        "user_agent.original": "Mozilla/5.0",
        "laravel.route.name": "checkout.store",
        "laravel.route.action": "App\\Http\\Controllers\\CheckoutController@store",
        "laravel.route.metadata": {
            "head": {
                "title": "Checkout"
            }
        }
    },
    "events": [
        {
            "type": "php_query",
            "startTimeUnixNano": 1710251999500000000,
            "endTimeUnixNano": 1710251999800000000,
            "attributes": {
                "db.system": "mysql",
                "db.statement": "insert into `orders` (`email`) values (?)",
                "db.sql.bindings": ["customer@example.com"]
            }
        },
        {
            "type": "php_log",
            "startTimeUnixNano": 1710251999900000000,
            "endTimeUnixNano": null,
            "attributes": {
                "log.message": "Creating order for customer@example.com",
                "log.level": "info"
            }
        }
    ],
    "stacktrace": [
        {
            "file": "/var/www/app/Actions/CreateOrder.php",
            "lineNumber": 28,
            "method": "execute",
            "class": "App\\Actions\\CreateOrder",
            "isApplicationFrame": true,
            "codeSnippet": {
                "26": "    public function execute(string $email): Order",
                "27": "    {",
                "28": "        return Order::create(['email' => $email]);",
                "29": "    }",
                "30": ""
            },
            "arguments": [
                {
                    "name": "$email",
                    "value": "customer@example.com",
                    "original_type": "string",
                    "passed_by_reference": false,
                    "is_variadic": false,
                    "truncated": false
                }
            ]
        },
        {
            "file": "/var/www/app/Http/Controllers/CheckoutController.php",
            "lineNumber": 32,
            "method": "store",
            "class": "App\\Http\\Controllers\\CheckoutController",
            "isApplicationFrame": true,
            "codeSnippet": null,
            "arguments": null
        }
    ]
}
```

