# Get Expense

**GET** `/users/{user_id}/expenses/{expense_id}`

Base URL: `https://live.savewithsail.com/api/v1`

Retrieves a single expense with full detail including adjudication, enrichment, merchant, and origin data.

## Authorization

- PartnerKey (http, bearer)

## Path parameters

- `user_id` (string, required)
  The Sail user id.
- `expense_id` (string, required)
  The Sail expense id.

## Responses

### 200

Expense details.

- `id` (string)
  The Sail expense id.
- `connection_id` (string)
  The connection this expense was sourced from.
- `external_transaction_id` (string)
  Echo of the customer-supplied id for expenses ingested through an `external` connection; null for Sail-sourced expenses. Join key back to the customer's own transaction store.
- `name` (string)
  The expense's display name.
- `description` (string)
  Human-readable description of the expense.
- `date` (string<date>)
  The transaction date.
- `amount` (number<float>)
  USD.
- `status` ("eligible" | "needs_review" | "ineligible" | "reimbursed" | "archived")
  The expense's current workflow status.
- `source_type` ("card" | "store" | "receipt_upload" | "external")
  How this expense entered Sail; pairs with the `source_type` list filter.
- `origin` (object)
  What the expense was derived from.
  - `type` ("transaction" | "product")
    `transaction` — derived from a bank/credit-card transaction (one expense per transaction, split via `parent_expense_id` after itemization). `product` — derived from an individual product line (store order data or an itemized receipt).
  - `detail` (string)
    The raw descriptor (transactions) or product title (products) the expense was derived from.
- `merchant` (object)
  The merchant this expense was incurred at, as resolved by enrichment. `supported_merchant_id` references the /merchants directory only when the merchant is one Sail can connect to for store data; it is null for the long tail of merchants that are recognized but not scrape-supported.
  - `name` (string)
    The merchant's display name.
  - `logo_url` (string)
    URL of the merchant's logo. Null if unavailable.
  - `supported_merchant_id` (string)
    The `/merchants` directory id, when Sail can connect to this merchant for store data. Null otherwise.
- `enrichment` (object)
  General transaction enrichment, independent of Section 213(d) adjudication.
  - `category` (string)
    General spend category.
  - `subcategory` (string)
    More granular spend subcategory, when available.
  - `mcc` (string)
    Merchant category code, when derived from a card transaction or supplied at ingest.
- `parent_expense_id` (string)
  Set when this expense is a line item split from another expense (e.g. itemization of a mixed-basket transaction after receipt review); null for top-level expenses.
- `section_213d_classification` (object)
  Section 213(d) eligibility adjudication. The review states pair with `origin.type`: `lmn_required` applies to product-origin expenses (a dual-purpose item that becomes eligible with a Letter of Medical Necessity); `itemization_required` applies to transaction-origin expenses (a mixed basket that needs an itemized receipt before line items can be adjudicated). Both surface as `needs_review` in the top-level workflow `status`.
  - `status` ("eligible" | "lmn_required" | "itemization_required" | "ineligible")
    The Section 213(d) review outcome.
  - `category` (string)
    Section 213(d) category.
  - `reasoning` (string)
    Human-readable explanation for the classification. Null if not available.
- `created_at` (string<date-time>)
  When the expense was created.
- `updated_at` (string<date-time>)
  When the expense was last updated.

Example:

```json
{
  "id": "string",
  "connection_id": "string",
  "external_transaction_id": "string",
  "name": "string",
  "description": "string",
  "date": "2024-01-01",
  "amount": 0,
  "status": "eligible",
  "source_type": "card",
  "origin": {
    "type": "transaction",
    "detail": "string"
  },
  "merchant": {
    "name": "Costco",
    "logo_url": "string",
    "supported_merchant_id": "mer_costco"
  },
  "enrichment": {
    "category": "Pharmacies",
    "subcategory": "Drug Stores",
    "mcc": "string"
  },
  "parent_expense_id": "string",
  "section_213d_classification": {
    "status": "eligible",
    "category": "Health Monitoring Devices",
    "reasoning": "string"
  },
  "created_at": "1970-01-01T00:00:00.000Z",
  "updated_at": "1970-01-01T00:00:00.000Z"
}
```

### default

Standard error envelope covering 400, 401, 403, 404, 429, and 500.

- `error` (object)
  The error detail.
  - `code` (string)
    Machine-readable code, e.g. `not_found`, `token_scope_mismatch`, `product_not_enabled`, `insufficient_key_scope`, `insufficient_token_scope`, `user_token_required`, `user_token_expired`, `invalid_user_token`, `invalid_key_configuration`, `connection_not_reconnectable`, `rate_limited`.
  - `message` (string)
    Human-readable error message. May change, so match on `error.code` instead.
  - `param` (string)
    The request field that caused the error, when applicable. Null otherwise.

Example:

```json
{
  "error": {
    "code": "string",
    "message": "string",
    "param": "string"
  }
}
```