# `MPP.Headers`
[🔗](https://github.com/ZenHive/mpp/blob/v0.10.0/lib/mpp/headers.ex#L1)

Parse and format the three MPP protocol wire-format headers.

## Headers

  * `WWW-Authenticate: Payment` — challenge header using RFC 9110 auth-param syntax
  * `Authorization: Payment` — credential header (scheme + base64url JSON blob)
  * `Payment-Receipt` — receipt header (bare base64url JSON blob)

The `Accept-Payment` client-preference header lives in `MPP.AcceptPayment`.

## Usage

    # Server: format a 402 challenge response header
    header_value = MPP.Headers.format_challenge(challenge)
    # → ~s(Payment id="x7Tg...", realm="api.example.com", method="stripe", ...)

    # Client: parse a 402 challenge from response
    {:ok, challenge} = MPP.Headers.parse_challenge(header_value)

    # Client: format credential for request
    header_value = MPP.Headers.format_credential(credential)
    # → "Payment eyJjaGFsbGVuZ2..."

    # Server: parse credential from request
    {:ok, credential} = MPP.Headers.parse_credential(header_value)

    # Server: format receipt for response
    header_value = MPP.Headers.format_receipt(receipt)

    # Client: parse receipt from response
    {:ok, receipt} = MPP.Headers.parse_receipt(header_value)

## API Functions
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `parse_receipt` | 1 | Parse a `Payment-Receipt` header value into a receipt struct. | `header: value` |
| `format_receipt` | 1 | Format a receipt as a `Payment-Receipt` header value (bare base64url JSON, no scheme prefix). | `receipt: value` |
| `parse_credential` | 1 | Parse an `Authorization: Payment` header value into a credential struct. | `header: value` |
| `format_credential` | 1 | Format a credential as an `Authorization: Payment` header value. | `credential: value` |
| `parse_challenges` | 1 | Parse a `WWW-Authenticate` header containing one or more `Payment` challenges. Splits on scheme boundaries, skips non-Payment schemes. Partial failures are tolerated: if some challenges parse and others fail, only the successful ones are returned (matching mppx `deserializeList` semantics). | `header: value` |
| `parse_challenge` | 1 | Parse a `WWW-Authenticate: Payment` header value into a challenge struct. | `header: value` |
| `format_challenge` | 1 | Format a challenge as a `WWW-Authenticate: Payment` header value with RFC 9110 auth-param syntax. | `challenge: value` |

# `format_challenge`

```elixir
@spec format_challenge(MPP.Challenge.t()) :: String.t()
```

Format a challenge as a `WWW-Authenticate: Payment` header value with RFC 9110 auth-param syntax.

## Parameters

  * `challenge` - Challenge struct to format (value)

## Returns

Header value string with quoted auth-params (`string`)

## Composes With

  * `parse_challenge`

```elixir
# descripex:contract
%{
  params: %{
    challenge: %{description: "Challenge struct to format", kind: :value}
  },
  returns: %{
    type: :string,
    description: "Header value string with quoted auth-params"
  },
  composes_with: [:parse_challenge]
}
```

# `format_credential`

```elixir
@spec format_credential(MPP.Credential.t()) :: String.t()
```

Format a credential as an `Authorization: Payment` header value.

## Parameters

  * `credential` - Credential struct to format (value)

## Returns

Header value with Payment scheme prefix and base64url JSON blob (`string`)

## Composes With

  * `parse_credential`

```elixir
# descripex:contract
%{
  params: %{
    credential: %{description: "Credential struct to format", kind: :value}
  },
  returns: %{
    type: :string,
    description: "Header value with Payment scheme prefix and base64url JSON blob"
  },
  composes_with: [:parse_credential]
}
```

# `format_receipt`

```elixir
@spec format_receipt(MPP.Receipt.t()) :: String.t()
```

Format a receipt as a `Payment-Receipt` header value (bare base64url JSON, no scheme prefix).

## Parameters

  * `receipt` - Receipt struct to format (value)

## Returns

Base64url-encoded JSON string (`string`)

## Composes With

  * `parse_receipt`

```elixir
# descripex:contract
%{
  params: %{receipt: %{description: "Receipt struct to format", kind: :value}},
  returns: %{type: :string, description: "Base64url-encoded JSON string"},
  composes_with: [:parse_receipt]
}
```

# `parse_challenge`

```elixir
@spec parse_challenge(String.t()) :: {:ok, MPP.Challenge.t()} | {:error, atom()}
```

Parse a `WWW-Authenticate: Payment` header value into a challenge struct.

## Parameters

  * `header` - Raw WWW-Authenticate header value string (value)

## Returns

`{:ok, challenge}` on success, `{:error, reason}` on failure (`tagged_tuple`)

## Errors

  * `:invalid_scheme`
  * `:missing_required_params`
  * `:duplicate_param`
  * `:invalid_auth_params`
  * `:request_too_large`
  * `:empty_id`
  * `:invalid_method`
  * `:invalid_request`
  * `:invalid_digest`

## Composes With

  * `format_challenge`

```elixir
# descripex:contract
%{
  params: %{
    header: %{
      description: "Raw WWW-Authenticate header value string",
      kind: :value
    }
  },
  errors: [:invalid_scheme, :missing_required_params, :duplicate_param,
   :invalid_auth_params, :request_too_large, :empty_id, :invalid_method,
   :invalid_request, :invalid_digest],
  returns: %{
    type: :tagged_tuple,
    description: "`{:ok, challenge}` on success, `{:error, reason}` on failure"
  },
  composes_with: [:format_challenge]
}
```

# `parse_challenges`

```elixir
@spec parse_challenges(String.t()) :: {:ok, [MPP.Challenge.t()]} | {:error, atom()}
```

Parse a `WWW-Authenticate` header containing one or more `Payment` challenges. Splits on scheme boundaries, skips non-Payment schemes. Partial failures are tolerated: if some challenges parse and others fail, only the successful ones are returned (matching mppx `deserializeList` semantics).

## Parameters

  * `header` - Raw WWW-Authenticate header value, possibly containing multiple challenges (value)

## Returns

`{:ok, [challenge]}` on success, `{:error, reason}` if no Payment challenges found or all fail to parse (`tagged_tuple`)

## Errors

  * `:no_payment_challenges`
  * `:invalid_scheme`
  * `:missing_required_params`
  * `:duplicate_param`
  * `:invalid_auth_params`
  * `:request_too_large`
  * `:empty_id`
  * `:invalid_method`
  * `:invalid_request`
  * `:invalid_digest`

## Composes With

  * `parse_challenge`
  * `format_challenge`

```elixir
# descripex:contract
%{
  params: %{
    header: %{
      description: "Raw WWW-Authenticate header value, possibly containing multiple challenges",
      kind: :value
    }
  },
  errors: [:no_payment_challenges, :invalid_scheme, :missing_required_params,
   :duplicate_param, :invalid_auth_params, :request_too_large, :empty_id,
   :invalid_method, :invalid_request, :invalid_digest],
  returns: %{
    type: :tagged_tuple,
    description: "`{:ok, [challenge]}` on success, `{:error, reason}` if no Payment challenges found or all fail to parse"
  },
  composes_with: [:parse_challenge, :format_challenge]
}
```

# `parse_credential`

```elixir
@spec parse_credential(String.t()) :: {:ok, MPP.Credential.t()} | {:error, atom()}
```

Parse an `Authorization: Payment` header value into a credential struct.

## Parameters

  * `header` - Raw Authorization header value string (value)

## Returns

`{:ok, credential}` on success, `{:error, reason}` on failure (`tagged_tuple`)

## Errors

  * `:invalid_scheme`
  * `:invalid_base64`
  * `:invalid_json`
  * `:missing_required_fields`
  * `:token_too_large`

## Composes With

  * `format_credential`

```elixir
# descripex:contract
%{
  params: %{
    header: %{
      description: "Raw Authorization header value string",
      kind: :value
    }
  },
  errors: [:invalid_scheme, :invalid_base64, :invalid_json,
   :missing_required_fields, :token_too_large],
  returns: %{
    type: :tagged_tuple,
    description: "`{:ok, credential}` on success, `{:error, reason}` on failure"
  },
  composes_with: [:format_credential]
}
```

# `parse_receipt`

```elixir
@spec parse_receipt(String.t()) :: {:ok, MPP.Receipt.t()} | {:error, atom()}
```

Parse a `Payment-Receipt` header value into a receipt struct.

## Parameters

  * `header` - Raw Payment-Receipt header value (bare base64url JSON) (value)

## Returns

`{:ok, receipt}` on success, `{:error, reason}` on failure (`tagged_tuple`)

## Errors

  * `:invalid_base64`
  * `:invalid_json`
  * `:missing_required_fields`
  * `:token_too_large`

## Composes With

  * `format_receipt`

```elixir
# descripex:contract
%{
  params: %{
    header: %{
      description: "Raw Payment-Receipt header value (bare base64url JSON)",
      kind: :value
    }
  },
  errors: [:invalid_base64, :invalid_json, :missing_required_fields,
   :token_too_large],
  returns: %{
    type: :tagged_tuple,
    description: "`{:ok, receipt}` on success, `{:error, reason}` on failure"
  },
  composes_with: [:format_receipt]
}
```

---

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