# Upload expense document

- Sandbox: `POST https://sandbox.payme.io/api/public/expenses`
- Production: `POST https://live.payme.io/api/public/expenses`

## Credentials

- Header `Authorization: Bearer <token>`

Upload an expense document for a seller via a publicly accessible file URL.

**Seller identification:** Exactly one method must be used per request:
- **Option A:** `sellerId` (UUID)
- **Option B:** `socialId` + `email`

Providing both or neither returns HTTP 400.

**Supported file formats:** PDF, JPG, PNG.

## Parameters

This endpoint takes no path, query or header parameters.

## Request body

Content type: `application/json`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `sellerId` | string | no | Seller UUID (use this OR socialId + email, not both) |
| `socialId` | string | no | Seller social/business ID number (must be paired with email) |
| `email` | string | no | Seller email address (must be paired with socialId) |
| `file` | string | yes | Publicly accessible URL of the expense document (PDF, JPG, or PNG) |

### Request example

```json
{
  "sellerId": "a6a9700f-8571-4f9b-bfae-ba943fb96982",
  "file": "https://i0.wp.com/avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/AK-3.png?ssl=1"
}
```

## Code samples

### curl

```bash
curl -X POST 'https://sandbox.payme.io/api/public/expenses' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <YOUR_TOKEN>' \
  --data-raw '{
  "sellerId": "a6a9700f-8571-4f9b-bfae-ba943fb96982",
  "file": "https://i0.wp.com/avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/AK-3.png?ssl=1"
}'
```

### Node.js

```javascript
const response = await fetch("https://sandbox.payme.io/api/public/expenses", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer <YOUR_TOKEN>",
  },
  body: JSON.stringify({
    "sellerId": "a6a9700f-8571-4f9b-bfae-ba943fb96982",
    "file": "https://i0.wp.com/avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/AK-3.png?ssl=1"
  }),
});

console.log(await response.text());
```

### Python

```python
import requests

response = requests.post(
    "https://sandbox.payme.io/api/public/expenses",
    headers={
        "Authorization": "Bearer <YOUR_TOKEN>",
    },
    json={
        "sellerId": "a6a9700f-8571-4f9b-bfae-ba943fb96982",
        "file": "https://i0.wp.com/avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/AK-3.png?ssl=1",
    },
)

print(response.text)
```

### PHP

```php
<?php

$body = <<<'BODY'
{
  "sellerId": "a6a9700f-8571-4f9b-bfae-ba943fb96982",
  "file": "https://i0.wp.com/avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/AK-3.png?ssl=1"
}
BODY;

$ch = curl_init('https://sandbox.payme.io/api/public/expenses');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer <YOUR_TOKEN>',
    ],
    CURLOPT_POSTFIELDS => $body,
]);

$response = curl_exec($ch);
curl_close($ch);

echo $response;
```

## Responses

### 200 — Expense document uploaded successfully (success)

| Field | Type | Description |
| --- | --- | --- |
| `payload` | object |  |
| `payload.id` | string | Unique identifier for the created expense record |
| `payload.capturedDate` | string | Timestamp when the expense was captured |
| `payload.sellerId` | string | Resolved seller UUID |

```json
{
  "payload": {
    "id": "a3504d9d-c187-48a0-8274-bea3b48e5663",
    "capturedDate": "2026-02-02T13:05:54.170Z",
    "sellerId": "a6a9700f-8571-4f9b-bfae-ba943fb96982"
  }
}
```

### 400 — Validation error (error)

| Field | Type | Description |
| --- | --- | --- |
| `statusCode` | integer | HTTP status code |
| `message` | string | Error message(s) |
| `error` | string | Error type |

```json
{
  "statusCode": 400,
  "message": [
    "socialId must be a number conforming to the specified constraints",
    "socialId should not be empty",
    "email must be an email",
    "email should not be empty",
    "sellerId must be a UUID",
    "sellerId should not be empty"
  ],
  "error": "Bad Request"
}
```

### 401 — Unauthorized (error)

| Field | Type | Description |
| --- | --- | --- |
| `error` | string |  |
| `error_description` | string |  |

```json
{
  "error": "unauthorized_client",
  "error_description": "Client authentication failed"
}
```

### 422 — Unprocessable entity — seller not resolved or file URL unreachable (error)

| Field | Type | Description |
| --- | --- | --- |
| `statusCode` | integer | HTTP status code |
| `message` | string | Error message(s) |
| `error` | string | Error type |

```json
{
  "statusCode": 422,
  "message": "Could not resolve seller",
  "error": "Unprocessable Entity"
}
```
