# Prove an Entry's Owner

The owner's signature over one of the entry's challenges: the entry is proven.

## Overview

- `signature`: on EVM, `0x` and 130 hex digits — the EIP-191 `personal_sign` of the challenge's `message` by the entry's address; on Solana, the base58 ed25519 signature (64 bytes) of the message's UTF-8 bytes by the entry's key.
- `200` with the entry: `proof.proven` `true`, `proof.method` `eip191` or `solana_ed25519`, `proof.provenAt`. Its version doesn't change; the challenge is used.
- **An entry waiting in `pending_approval`** — for this proof, where your settings require one — **starts its cooling** from the proof: `cooling` until `activeAt`, or `active` with a cooling period of 0; `approval.approvedBy` `null`. An entry already cooling or active keeps its status.
- Checked in this order: the entry (`404`, `409` `ADDRESS_BOOK_ENTRY_FINAL`); the challenge is the entry's (`404` `ADDRESS_BOOK_CHALLENGE_NOT_FOUND`), not used (`409` `ADDRESS_BOOK_CHALLENGE_USED`), not expired (`410` `ADDRESS_BOOK_CHALLENGE_EXPIRED`), of the entry's current address (`409` `ADDRESS_BOOK_CHALLENGE_STALE`); the signature (`400` `ADDRESS_BOOK_SIGNATURE_MALFORMED` or `ADDRESS_BOOK_SIGNATURE_WRONG_SIGNER` with `details.attemptsLeft`; the fifth wrong one `409` `ADDRESS_BOOK_CHALLENGE_BURNT`).
- For `owner`, `tenantadmin`, `non_signing_admin` and `editor`.

## Endpoint

### `POST /v1/address-book/entries/{entryId}/proof/verify`

Authentication: bearer token required.

Proves an external entry with its owner's signature.

**Path parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `entryId` | string (uuid) | yes | The entry's id |

**Request body**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `challengeId` | string (uuid) | yes | One of the entry's challenges |
| `signature` | string | yes | 1–200 characters: EVM `0x` + 130 hex; Solana base58 |

**Responses**

`200` Proven

```json
{
  "id": "8f3c2a71-5d4e-4b9a-a6c1-2e7f9d0b3c58",
  "accountId": null,
  "kind": "external",
  "family": "evm",
  "network": "mainnet",
  "chain": "base",
  "chainId": null,
  "address": "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed",
  "walletId": null,
  "label": "Supplier payouts",
  "tags": ["suppliers"],
  "customerRefId": "SUP-0042",
  "status": "cooling",
  "version": 1,
  "requestedBy": "0d2f6b8a-4c1e-4a93-b7d5-2e9f1c3a8b60",
  "requestedScope": "tenant",
  "requestedAt": "2026-10-08T08:00:12.000Z",
  "approval": {
    "approvedBy": null,
    "approvedScope": "tenant",
    "approvedAt": "2026-10-08T08:10:41.000Z",
    "requiredApprovals": 0
  },
  "coolingPeriodSeconds": 86400,
  "activeAt": "2026-10-09T08:10:41.000Z",
  "coolingSecondsLeft": 86400,
  "proof": { "proven": true, "method": "eip191", "provenAt": "2026-10-08T08:10:41.000Z" },
  "rejectedBy": null,
  "rejectedAt": null,
  "removedBy": null,
  "removedAt": null,
  "createdAt": "2026-10-08T08:00:12.000Z",
  "updatedAt": "2026-10-08T08:10:41.000Z"
}
```

`400` Wrong signer

```json
{
  "statusCode": 400,
  "error": "BadRequestError",
  "message": "The signature is not the address's over this challenge",
  "details": { "code": "ADDRESS_BOOK_SIGNATURE_WRONG_SIGNER", "attemptsLeft": 4 }
}
```

`410` Expired

```json
{
  "statusCode": 410,
  "error": "GoneError",
  "message": "This challenge has expired: ask for a new one",
  "details": { "code": "ADDRESS_BOOK_CHALLENGE_EXPIRED" }
}
```

**Example request**

```bash
curl -X POST https://api.aureahub.com/v1/address-book/entries/$ENTRY_ID/proof/verify \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "challengeId": "c47e0b19-3d6a-4f25-9b81-6e2d5a0c7f34", "signature": "0x…130 hex digits…" }'
```

---

Web version: https://docs.aureahub.com/#address-book-proof-verify
