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

# Upload a hotel inventory file to Mapping.Travel

> Upload a CSV, JSON, Excel, or Parquet hotel inventory file to Mapping.Travel for processing. Returns an uploadId you can use to track progress.

Use this endpoint to submit a hotel inventory file for processing. Mapping.Travel accepts CSV, JSON, Excel (.xlsx), and Parquet formats up to 500MB. Once uploaded, use the returned `uploadId` to poll for status. Uploading the same file twice returns the same `uploadId` — the operation is idempotent.

## Request

**`POST https://api.mapping.travel/api/v1/inventory`**

Content-Type: `multipart/form-data`

<ParamField body="file" type="file" required>
  The hotel inventory file to upload. Supported formats: CSV, JSON, Excel (.xlsx), Parquet. Maximum file size is 500MB.
</ParamField>

<ParamField body="supplierCode" type="string">
  Optional supplier code used for ID-to-ID mapping (e.g., `expedia`, `booking`). When provided, property IDs in your file are matched against the specified supplier's ID space.
</ParamField>

## Example

<CodeGroup>
  ```bash curl theme={null} theme={null}
  curl -X POST https://api.mapping.travel/api/v1/inventory \
    -H "Authorization: Bearer <your-token>" \
    -F "file=@hotels.csv" \
    -F "supplierCode=expedia"
  ```

  ```bash curl (no supplier code) theme={null} theme={null}
  curl -X POST https://api.mapping.travel/api/v1/inventory \
    -H "Authorization: Bearer <your-token>" \
    -F "file=@inventory.parquet"
  ```
</CodeGroup>

## Response

A successful upload returns HTTP `201 Created`.

<ResponseField name="uploadId" type="string">
  UUID identifying this upload record. Use this to check status, download, or cancel.
</ResponseField>

<ResponseField name="status" type="string">
  Initial status of the upload. Will be `PENDING` immediately after submission.
</ResponseField>

<ResponseField name="filename" type="string">
  Original filename as received by the server.
</ResponseField>

<ResponseField name="fileFormat" type="string">
  Detected file format: `CSV`, `JSON`, `EXCEL`, or `PARQUET`.
</ResponseField>

<ResponseField name="rowCount" type="integer">
  Total number of data rows detected. May be `0` until processing begins.
</ResponseField>

<ResponseField name="validRows" type="integer">
  Number of rows that passed validation. May be `0` until processing completes.
</ResponseField>

<ResponseField name="invalidRows" type="integer">
  Number of rows that failed validation. May be `0` until processing completes.
</ResponseField>

<ResponseField name="supplierCode" type="string">
  The supplier code provided in the request, if any.
</ResponseField>

<ResponseField name="createdAt" type="string">
  ISO 8601 timestamp of when the upload record was created.
</ResponseField>

<Note>
  Processing is asynchronous. After receiving a `201`, poll `GET /api/v1/inventory/{uploadId}` to track progress until the status transitions to `COMPLETED` or `FAILED`.
</Note>

## Error codes

| Code | Description                                                                       |
| ---- | --------------------------------------------------------------------------------- |
| 400  | Invalid request — missing file, empty file, or malformed request                  |
| 401  | Missing or invalid Bearer token                                                   |
| 413  | File exceeds the 500MB size limit                                                 |
| 415  | Unsupported file format — only CSV, JSON, Excel (.xlsx), and Parquet are accepted |
| 429  | Rate limit exceeded — reduce upload frequency and retry                           |
