# idvalidate/v1 — Polish ID checksum validators

Validates Polish national/business identifiers by checking their embedded
checksum digit(s). Purely offline, deterministic math — no external lookups,
no confirmation that a number is *assigned* to anyone, only that it is
*well-formed*.

## Endpoints

All three take the same request shape and return the same base response
shape:

**Request**

```json
{ "value": "44051401359" }
```

**Response — valid**

```json
{ "valid": true }
```

**Response — invalid**

```json
{ "valid": false, "reason": "invalid checksum" }
```

Both responses are HTTP 200 — an invalid number is a successful validation
that answers "no", not a client error. HTTP 400 with `{"error": "..."}` is
reserved for a malformed request body (bad JSON).

`value` should contain only digits (no spaces or dashes); anything else is
reported via `reason`.

### `POST /v1/idvalidate/pesel`

11-digit Polish national identification number (PESEL). Checksum uses
weights `1 3 7 9 1 3 7 9 1 3` over the first 10 digits; control digit is
`(10 - sum mod 10) mod 10`.

On success the response also decodes the date of birth and sex embedded in
the number:

```json
{ "valid": true, "birthDate": "1944-05-14", "sex": "male" }
```

The century is encoded in the month field: `01-12` → 1900s, `21-32` → 2000s,
`41-52` → 2100s, `61-72` → 2200s, `81-92` → 1800s. Sex is derived from the
10th digit: odd = male, even = female. A checksum-valid number with an
impossible calendar date (e.g. Feb 30) is still reported invalid.

### `POST /v1/idvalidate/nip`

10-digit Polish tax identification number (NIP). Checksum uses weights
`6 5 7 2 3 4 5 6 7` over the first 9 digits, `sum mod 11` must equal the
10th digit. A `sum mod 11` of `10` is itself invalid — no NIP has that
control value.

### `POST /v1/idvalidate/regon`

9- or 14-digit Polish business registry number (REGON).

- **9-digit:** weights `8 9 2 3 4 5 6 7` over the first 8 digits, `sum mod 11`
  (mapped `10 → 0`) must equal the 9th digit.
- **14-digit:** the first 9 digits must themselves be a valid 9-digit REGON,
  *and* weights `2 4 8 5 0 9 7 3 6 1 2 4 8` over the first 13 digits
  (`sum mod 11`, mapped `10 → 0`) must equal the 14th digit.

## Examples

```bash
curl -s -X POST https://apished.com/v1/idvalidate/pesel \
  -H 'Content-Type: application/json' \
  -d '{"value": "44051401359"}'
# {"valid":true,"birthDate":"1944-05-14","sex":"male"}

curl -s -X POST https://apished.com/v1/idvalidate/nip \
  -H 'Content-Type: application/json' \
  -d '{"value": "5260001246"}'
# {"valid":true}

curl -s -X POST https://apished.com/v1/idvalidate/regon \
  -H 'Content-Type: application/json' \
  -d '{"value": "123456785"}'
# {"valid":true}
```

## Files

- `idvalidate.go` — module wiring (routes, HTTP handlers)
- `validators.go` — pure checksum logic for PESEL, NIP, REGON
- `validators_test.go` — test vectors covering valid, invalid-checksum,
  wrong-length, non-digit, and (for PESEL) invalid-calendar-date cases
