# `PaperTiger.Error`
[🔗](https://github.com/EnaiaInc/paper_tiger/blob/v1.2.2/lib/paper_tiger/error.ex#L1)

Stripe-compatible error responses.

Matches Stripe's error structure and HTTP status codes.

## Error Types

- `invalid_request_error` - Bad request (400)
- `api_error` - Server error (500)
- `card_error` - Card declined (402)
- `rate_limit_error` - Too many requests (429)

## Examples

    # Not found error
    PaperTiger.Error.not_found("customer", "cus_123")
    # => %PaperTiger.Error{
    #      type: "invalid_request_error",
    #      message: "No such customer: 'cus_123'",
    #      status: 404
    #    }

    # Card declined
    PaperTiger.Error.card_declined()
    # => %PaperTiger.Error{
    #      type: "card_error",
    #      code: "card_declined",
    #      message: "Your card was declined.",
    #      status: 402
    #    }

# `t`

```elixir
@type t() :: %PaperTiger.Error{
  __exception__: true,
  code: String.t() | nil,
  decline_code: String.t() | nil,
  message: String.t() | nil,
  param: String.t() | nil,
  status: integer() | nil,
  type: String.t() | nil
}
```

# `api_error`

```elixir
@spec api_error(String.t()) :: t()
```

Creates an API error (500).

# `card_declined`

```elixir
@spec card_declined(keyword()) :: t()
```

Creates a card declined error (402).

## Options

- `:code` - Decline code (default: "card_declined")

Possible codes:
- `card_declined` - Generic decline
- `insufficient_funds` - Not enough money
- `expired_card` - Card expired
- `incorrect_cvc` - CVC check failed

# `idempotency_key_in_use`

```elixir
@spec idempotency_key_in_use(String.t()) :: t()
```

Creates an idempotency conflict error (400).

Mirrors Stripe's `idempotency_key_in_use` behavior for the same key with
different request parameters.

# `invalid_request`

```elixir
@spec invalid_request(String.t(), String.t() | atom() | nil) :: t()
```

Creates an invalid request error (400).

If a param is provided, it will be appended to the message in the format:
"message: param"

## Examples

    PaperTiger.Error.invalid_request("Missing required parameter", :customer)
    # => %PaperTiger.Error{
    #      message: "Missing required parameter: customer",
    #      param: "customer",
    #      status: 400,
    #      type: "invalid_request_error"
    #    }

# `not_found`

```elixir
@spec not_found(String.t(), String.t()) :: t()
```

Creates a not found error (404).

Returns the same error format as Stripe's API for missing resources.

## Param Values by Resource Type

Stripe uses different `param` values depending on the resource:
- `customer`, `product`, `subscription` -> `"id"`
- `price` -> `"price"`
- `plan` -> `"plan"`
- `invoice` -> `"invoice"`
- `payment_intent` -> `"intent"`

## Examples

    PaperTiger.Error.not_found("customer", "cus_123")
    # => %PaperTiger.Error{
    #      code: "resource_missing",
    #      message: "No such customer: 'cus_123'",
    #      param: "id",
    #      status: 404,
    #      type: "invalid_request_error"
    #    }

# `rate_limit`

```elixir
@spec rate_limit() :: t()
```

Creates a rate limit error (429).

# `to_json`

```elixir
@spec to_json(t()) :: map()
```

Converts error to Stripe's JSON format.

## Examples

    PaperTiger.Error.not_found("customer", "cus_123")
    |> PaperTiger.Error.to_json()
    # => %{
    #   error: %{
    #     type: "invalid_request_error",
    #     message: "No such customer: 'cus_123'"
    #   }
    # }

---

*Consult [api-reference.md](api-reference.md) for complete listing*
