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

# Authentication

> Access Protocol v1 — ECDSA-signed requests over secp256k1.

The BlooBank API uses the **Access Protocol** — a request-signing scheme based on ECDSA `secp256k1` signatures over a canonical request string. Every request carries four headers (`X-Access-Key`, `X-Access-Timestamp`, `X-Access-Request-Id`, `X-Access-Signature`); a missing or mis-formed header is rejected before any signature check.

There are no static API tokens. Your **private key** stays on your infrastructure. BlooBank holds only the matching **public key**, used to verify your signatures.

<Info>
  **Why signed requests instead of static tokens?** A leaked API token gives an attacker full access until you rotate it. A leaked signature is worthless — it is bound to one request, at one moment in time, with one body. The private key never crosses the wire.
</Info>

## At a glance

<Steps>
  <Step title="Generate a keypair locally">
    Create an ECDSA `secp256k1` private key on your infrastructure and derive the public half. The private key never leaves your environment.
  </Step>

  <Step title="Register the public key with BlooBank">
    Send the public key (hex-encoded, 130 characters starting with `04`) to your integration support contact. BlooBank returns an **Access Key** — your credential identifier.
  </Step>

  <Step title="Sign every request">
    For each API call, build a canonical request string, hash it with SHA-256, sign it with your private key, and attach the four `X-Access-*` headers.
  </Step>

  <Step title="BlooBank verifies">
    The platform recomputes the canonical string, looks up your public key by `X-Access-Key`, and verifies the signature. Valid → request flows through. Invalid → `401 SIGNATURE_INVALID`.
  </Step>
</Steps>

```mermaid theme={"dark"}
sequenceDiagram
    autonumber
    participant I as Your service
    participant B as BlooBank

    I->>I: Generate ECDSA keypair (locally)
    I->>B: Send public key (onboarding, one-time)
    B->>I: Return Access Key

    Note over I,B: For every request:
    I->>I: Build canonical string
    I->>I: Sign with private key
    I->>B: Send signed request (4 headers)
    B->>B: Recompute canonical, verify signature
    alt Valid
      B->>I: 2xx response
    else Invalid
      B->>I: 401 SIGNATURE_INVALID
    end
```

## What you need

| Item        | Source                                                                     |
| ----------- | -------------------------------------------------------------------------- |
| Access Key  | Provided by BlooBank during onboarding (after public-key registration).    |
| Private key | Generated by **you**, locally. Stored in a secret manager.                 |
| Public key  | Derived from the private key. **Sent once** to BlooBank during onboarding. |
| Base URL    | `https://txengine.bloobank.com/txengine/v1`                                |

## The four required headers

| Header                | Format                               | Purpose                                                                 |
| --------------------- | ------------------------------------ | ----------------------------------------------------------------------- |
| `X-Access-Key`        | Opaque string                        | Identifies which credential is making the request.                      |
| `X-Access-Timestamp`  | Unix epoch in **milliseconds** (UTC) | Bounds the freshness window. Must be within ±10 seconds of server time. |
| `X-Access-Request-Id` | UUID v4 (recommended)                | Prevents replay. Deduplicated for 1 hour against the same Access Key.   |
| `X-Access-Signature`  | Base64-encoded ECDSA signature       | Proves the request was constructed by the holder of the private key.    |

Failing any of these is rejected before further processing:

| Reason                    | HTTP |
| ------------------------- | ---: |
| `MISSING_HEADER`          |  400 |
| `TIMESTAMP_INVALID`       |  400 |
| `TIMESTAMP_SKEW_EXCEEDED` |  401 |
| `SIGNATURE_INVALID`       |  401 |
| `REPLAY_DETECTED`         |  401 |

See [Error catalog](/get-started/errors/error-catalog) for the full list.

## Curve choice

The default signing curve is `secp256k1` — the same curve used by Bitcoin and Ethereum, broadly supported by every mainstream crypto library. Your onboarding agreement specifies which curve is registered for your credential; if BlooBank assigned a different curve, every other rule below stays identical, only the curve changes.

## Next

<CardGroup cols={3}>
  <Card title="Generate your keys" icon="key" href="/get-started/authentication/generate-keys">
    Create your ECDSA keypair with OpenSSL.
  </Card>

  <Card title="Sign a request" icon="signature" href="/get-started/authentication/sign-request">
    Build the canonical string, hash, sign, attach the headers.
  </Card>

  <Card title="Code examples" icon="code" href="/get-started/authentication/code-examples">
    Working signer clients in six languages.
  </Card>
</CardGroup>
