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

# Create Case

> Open a support case on a Zinc order, with an optional message and attachments.

Open a support case when you need Zinc's help with an order: a package that never arrived, a damaged item, a billing question. Zinc support replies on the case, and the whole conversation stays on it. Follow it with [Get Case](https://www.zinc.com/docs/v2/api-reference/cases/get-case.md) or the [case webhooks](https://www.zinc.com/docs/v2/api-reference/introduction/webhooks.md#case-events).

The request is a multipart form, not JSON, so photos and PDFs can be attached in the same call:

```bash theme={null}
curl -X POST "https://api.zinc.com/cases" \
  -H "Authorization: Bearer <your_api_key>" \
  -F "order_id=550e8400-e29b-41d4-a716-446655440000" \
  -F "reason=damaged_or_wrong_item" \
  -F "body=The mug arrived cracked. Photo attached." \
  -F "files=@cracked-mug.jpg"
```

## Request

* **order\_id**: the order the case is about. Any order your team can see works.
* **reason**: one of the reasons below.
* **body**: your message, up to 5,000 characters. It can be empty if you attach at least one file.
* **return\_request\_id** (optional): links the case to a [return request](https://www.zinc.com/docs/v2/api-reference/returns/get-return.md) on the same order. Required when `reason` is `return`.
* **files** (optional): up to 5 attachments, 25 MB each, as JPEG, PNG, WebP, HEIC or PDF. Repeat the `files` field once per file.

## Reasons

The reason routes the case to the right people. It doesn't trigger anything automatically: a `damaged_or_wrong_item` case doesn't file a return, and a `cancellation` case doesn't cancel the order. To start a return, use [Create Return Request](https://www.zinc.com/docs/v2/api-reference/returns/create-return.md).

| Reason | When to use |
| - | - |
| `not_received` | The order, or a package on it, never arrived |
| `missing_item` | A package arrived, but an item from it is missing |
| `late` | The order is past its estimated delivery date and hasn't arrived |
| `damaged_or_wrong_item` | An item arrived damaged, or a different item came instead |
| `cancellation` | A question about a cancellation, or a request to cancel |
| `address_change` | The shipping address needs to change |
| `return` | A question about an existing return request. Pass its `return_request_id` |
| `billing` | A charge, credit or wallet question about the order |
| `other` | Anything else. Explain in `body` |

## When a case can be opened

* The order is `order_placed`, `cancelled` or `cancelled_by_retailer`. Otherwise the call fails with `400`, `code: "case_not_allowed"` and `details.reason: "order_status"`.
* The order is inside the **case window**: 30 days after the latest delivery or estimated delivery date across its packages, or 90 days after the order was created when it has no tracking yet. Past the window, the call fails with `400`, `code: "case_not_allowed"` and `details.reason: "window_closed"`.
* The order has no other open case. An order has at most one case that isn't `closed`. A second one fails with `409`, and `details.case_id` names the open case, so reply on that one with [Post Case Message](https://www.zinc.com/docs/v2/api-reference/cases/post-case-message.md) instead:

```json theme={null}
{
  "code": "already_exists",
  "message": "There is already an open case on this order",
  "details": {
    "resource": "SupportCase",
    "identifier": "550e8400-e29b-41d4-a716-446655440000",
    "conflict": "case_already_open",
    "case_id": "3f2c9a8e-1b4d-4e6f-9a7b-2c8d5e1f0a3b"
  }
}
```

## Other errors

A failed request saves nothing: no case, message or file.

| Status | `code` | Cause |
| - | - | - |
| `404` | `not_found` | No order with that ID, or it belongs to another team |
| `413` | | A file is over 25 MB |
| `415` | | A file isn't JPEG, PNG, WebP, HEIC or PDF |
| `422` | `validation_error` | No message and no files, a message over 5,000 characters, more than 5 files, `reason=return` without `return_request_id`, or a `return_request_id` from a different order |

## Response

The new case with `status: "open"` and your message as the first entry in `messages`. See [Get Case](https://www.zinc.com/docs/v2/api-reference/cases/get-case.md) for the full shape.


## OpenAPI

````yaml versions/latest.json POST /cases
openapi: 3.1.0
info:
  title: Zinc
  summary: >-
    Zinc lets you search, buy, and return items from top online retailers with a
    single API.
  description: >-
    Search, buy, and return items from top online retailers with a single API.
    Supports AI agent ordering via MPP (HTTP 402) — no account required.
    Supported retailers include 1-800-Flowers, Ace Hardware, Amazon, Amazon CA,
    Amazon DE, Amazon FR, Amazon MX, Amazon UK, Barnes & Noble, Best Buy, Chewy,
    Gap, and 18 more. Ships to the US and 6 other countries (CA, DE, FR, GB, IT,
    MX). The listed retailers are the ones Zinc verifies with daily test orders,
    not the limit of what Zinc can buy from: checkout is attempted at most
    online stores, including Shopify-hosted ones. To ask about a specific store
    before ordering, call GET /retailers/check?url=... — it answers whether Zinc
    will attempt that URL.
  version: '2026-10-16'
  x-logo:
    url: https://mintlify.s3.us-west-1.amazonaws.com/zinc/logo/light.png
  contact:
    name: Zinc API Support
    email: support@zinc.com
    url: https://zinc.com/docs
  x-guidance: >-
    Zinc lets AI agents buy products from online retailers via a single API. Use
    POST /agent/orders to place an order — no Zinc account needed, payment is
    handled via MPP (HTTP 402 flow). Provide a product URL from a supported
    retailer, a shipping address, and max_price in cents. The API charges
    max_price + $1 API fee upfront and refunds the difference on completion. To
    find products first, the /agent/* data endpoints (search, products/search,
    products/offers, products/details) are MPP-paid at $0.01 per call;
    /agent/search returns orderable URLs to feed straight into /agent/orders.
    GET /retailers lists supported retailers for free (no payment or account).
    Authenticated equivalents (orders, products, managed-accounts) require a
    Bearer token (API key prefixed zn_); those orders are paid from a prefunded
    wallet — GET /wallet/me returns the spendable balance and per-order fee, so
    check it before POST /orders to avoid a 402. Orders are strict by default:
    if the gift option can't be applied or any item can't be bought, the whole
    order fails. When the user wants whatever can be shipped, send fulfillment:
    {"gift": "best_effort", "items": "best_effort"} and read
    fulfillment.concessions on the order to see what was relaxed. max_price is
    never relaxed. Docs: https://zinc.com/docs Supported retailers include
    1-800-Flowers, Ace Hardware, Amazon, Amazon CA, Amazon DE, Amazon FR, Amazon
    MX, Amazon UK, Barnes & Noble, Best Buy, Chewy, Gap, and 18 more, shipping
    to the US and 6 other countries (CA, DE, FR, GB, IT, MX). The listed
    retailers are the ones Zinc verifies with daily test orders, not the limit
    of what Zinc can buy from: checkout is attempted at most online stores,
    including Shopify-hosted ones. To ask about a specific store before
    ordering, call GET /retailers/check?url=... — it answers whether Zinc will
    attempt that URL.
  x-supported-retailers:
    - 1-800-Flowers
    - Ace Hardware
    - Amazon
    - Amazon CA
    - Amazon DE
    - Amazon FR
    - Amazon MX
    - Amazon UK
    - Barnes & Noble
    - Best Buy
    - Chewy
    - Gap
    - Grainger
    - IBS
    - Lowe's
    - Macys
    - McMaster-Carr
    - Partstown
    - Pokémon Center
    - Sephora
    - Target
    - The Home Depot
    - TikTok
    - Uniqlo
    - Walmart
    - Wayfair
    - Zinc
    - eBay
    - libraccio
    - zazzle
  x-supported-countries:
    - US
    - CA
    - DE
    - FR
    - GB
    - IT
    - MX
servers:
  - url: https://api.zinc.com
    description: Production
security:
  - BearerAuth: []
paths:
  /cases:
    post:
      tags:
        - cases
      summary: Create Case
      description: >-
        Open a support case on an order.


        Multipart form: `order_id`, `reason`, `body`, optional
        `return_request_id`,

        and up to 5 `files` (JPEG, PNG, WebP, HEIC or PDF, 25 MB each). An order
        has

        at most one open case at a time. `reason=return` is only valid together

        with `return_request_id`.
      operationId: create_case_cases_post
      parameters:
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            title: Authorization
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/Body_create_case_cases_post'
      responses:
        '201':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CaseResponse'
        '400':
          description: >-
            The order can't take a case: wrong status, or past the case window
            (30 days after delivery / estimated delivery, 90 days after the
            order otherwise)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: >-
            The order already has an open case — reply on it instead
            (`details.case_id`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
components:
  schemas:
    Body_create_case_cases_post:
      properties:
        order_id:
          type: string
          format: uuid
          title: Order Id
        reason:
          $ref: '#/components/schemas/CaseReason'
        body:
          type: string
          title: Body
          default: ''
        return_request_id:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          title: Return Request Id
        files:
          items:
            type: string
            format: binary
          type: array
          title: Files
          default: []
      type: object
      required:
        - order_id
        - reason
      title: Body_create_case_cases_post
    CaseResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
        order_id:
          type: string
          format: uuid
          title: Order Id
        return_request_id:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          title: Return Request Id
        reason:
          $ref: '#/components/schemas/CaseReason'
        status:
          $ref: '#/components/schemas/CaseStatus'
          description: >-
            `open` — waiting on Zinc. `waiting_on_customer` — Zinc replied and
            is waiting on you. `on_hold` — waiting on the retailer or carrier.
            `closed` — resolved; replying reopens it within the case window.
        credited_amount:
          type: integer
          title: Credited Amount
          description: >-
            Total wallet credit issued from this case, in cents (net of
            reversals).
          default: 0
        opened_by_name:
          anyOf:
            - type: string
            - type: 'null'
          title: Opened By Name
          description: >-
            Who opened the case: a teammate's name, or `Zinc support` when Zinc
            reached out. (The `case.created` webhook's `opened_by` is the side
            instead: `customer` or `zinc`.)
        created_at:
          type: string
          format: date-time
          title: Created At
        updated_at:
          type: string
          format: date-time
          title: Updated At
        closed_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Closed At
        messages:
          items:
            $ref: '#/components/schemas/CaseMessageResponse'
          type: array
          title: Messages
          default: []
      type: object
      required:
        - id
        - order_id
        - reason
        - status
        - created_at
        - updated_at
      title: CaseResponse
    ErrorResponse:
      properties:
        error:
          $ref: '#/components/schemas/ErrorDetail'
      type: object
      required:
        - error
      title: ErrorResponse
      description: Wrapper for error responses.
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    CaseReason:
      type: string
      enum:
        - not_received
        - missing_item
        - late
        - damaged_or_wrong_item
        - cancellation
        - address_change
        - return
        - billing
        - other
      title: CaseReason
      description: |-
        What a support case is about. Routing and reporting only — no reason
        triggers automation.
    CaseStatus:
      type: string
      enum:
        - open
        - waiting_on_customer
        - on_hold
        - closed
      title: CaseStatus
      description: >-
        Whose move it is on a support case.


        Only ``closed`` is terminal, and not even that for long: a customer
        reply

        inside the open window reopens a closed case rather than starting a new
        one.
    CaseMessageResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
        author:
          type: string
          enum:
            - customer
            - zinc
            - system
          title: Author
          description: >-
            `customer` (you or a teammate), `zinc` (our support team), or
            `system` (status changes, reopens, credits).
        author_name:
          anyOf:
            - type: string
            - type: 'null'
          title: Author Name
          description: >-
            Who wrote it: the teammate's name for `customer` messages, `Zinc
            support` for `zinc`, null for `system` lines.
        from_you:
          type: boolean
          title: From You
          description: True when the caller wrote this message.
          default: false
        body:
          type: string
          title: Body
        attachments:
          items:
            $ref: '#/components/schemas/CaseAttachment'
          type: array
          title: Attachments
          default: []
        created_at:
          type: string
          format: date-time
          title: Created At
      type: object
      required:
        - id
        - author
        - body
        - created_at
      title: CaseMessageResponse
    ErrorDetail:
      properties:
        code:
          $ref: '#/components/schemas/ErrorCode'
        message:
          type: string
          title: Message
        details:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Details
      type: object
      required:
        - code
        - message
      title: ErrorDetail
      description: Standard error response body.
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
    CaseAttachment:
      properties:
        id:
          type: string
          format: uuid
          title: Id
        filename:
          type: string
          title: Filename
        content_type:
          type: string
          title: Content Type
        size_bytes:
          type: integer
          title: Size Bytes
        url:
          anyOf:
            - type: string
            - type: 'null'
          title: Url
          description: >-
            Presigned download URL, valid for 7 days from the response. Re-fetch
            the case for a fresh one.
      type: object
      required:
        - id
        - filename
        - content_type
        - size_bytes
      title: CaseAttachment
    ErrorCode:
      type: string
      enum:
        - unauthorized
        - forbidden
        - invalid_token
        - token_expired
        - not_found
        - already_exists
        - validation_error
        - insufficient_funds
        - authorization_pending
        - slow_down
        - expired_token
        - access_denied
        - payment_failed
        - payment_method_required
        - payment_required
        - invalid_payment_method
        - invalid_shipping_address
        - url_unreachable
        - non_us_retailer
        - unsupported_retailer
        - unsupported_country
        - retailer_country_not_supported
        - guest_checkout_not_supported
        - invalid_variant
        - out_of_stock
        - shipping_unavailable
        - order_not_cancellable
        - return_not_allowed
        - case_not_allowed
        - external_service_error
        - stripe_error
        - stytch_error
        - internal_error
        - bad_request
        - rate_limit_exceeded
        - service_unavailable
      title: ErrorCode
      description: Standardized error codes for the API.
  securitySchemes:
    BearerAuth:
      type: apiKey
      in: header
      name: Authorization
      description: Zinc API key (Bearer zn_...)

````

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