# Developer

Self-service integration plumbing — your webhook endpoints and their secrets, a test delivery, a log of recent API requests, and a live event stream. The API key itself is managed from the dashboard (Settings → API keys), not through the API.

8 endpoints. Generated from `docs/openapi.yaml` v1.0.0.

| Endpoint | Summary |
| --- | --- |
| [`GET /v1/developer/webhooks`](#get-v1-developer-webhooks) | List your webhook endpoints |
| [`POST /v1/developer/webhooks`](#post-v1-developer-webhooks) | Add a webhook endpoint |
| [`POST /v1/developer/webhooks/{id}`](#post-v1-developer-webhooks-id) | Enable or disable an endpoint |
| [`DELETE /v1/developer/webhooks/{id}`](#delete-v1-developer-webhooks-id) | Delete an endpoint |
| [`POST /v1/developer/webhooks/{id}/regenerate`](#post-v1-developer-webhooks-id-regenerate) | Regenerate an endpoint's signing secret |
| [`POST /v1/developer/webhooks/{id}/test`](#post-v1-developer-webhooks-id-test) | Send a signed test event |
| [`GET /v1/developer/logs`](#get-v1-developer-logs) | Your recent API requests |
| [`GET /v1/events`](#get-v1-events) | Live event stream (Server-Sent Events) |

## GET /v1/developer/webhooks

**List your webhook endpoints**  ·  _Auth: bearer API key_  ·  `operationId: listWebhookEndpoints`

#### Responses

| Status | Body | Meaning |
| --- | --- | --- |
| `200` | `object` | Endpoints (secret shown as an 8-char hint only). |
| `401` | `Error` | Missing, malformed or unknown API key. |

**`200` response body**

| Field | Type | Description |
| --- | --- | --- |
| `endpoints` | `object[]` | — |
| `endpoints[].id` | `integer` | — |
| `endpoints[].url` | `string` | — |
| `endpoints[].enabled` | `boolean` | — |
| `endpoints[].created_at` | `string<date-time>` | — |
| `endpoints[].secret_hint` | `string` | First 8 characters of the signing secret. |
| `endpoints[].secret` | `string` | Full signing secret — present ONLY on create/regenerate. |

```json
{
  "endpoints": [
    {
      "id": 1,
      "url": "string",
      "enabled": true,
      "created_at": "2026-08-31T09:15:00.000Z",
      "secret_hint": "string",
      "secret": "string"
    }
  ]
}
```

#### Example request

```bash
curl -X GET 'https://api.cryptoinfra.build/v1/developer/webhooks' \
  -H 'Authorization: Bearer ck_live_your_key'
```

## POST /v1/developer/webhooks

**Add a webhook endpoint**  ·  _Auth: bearer API key_  ·  `operationId: createWebhookEndpoint`

Every event (deposits, withdrawals, card activity, payments) is delivered to each enabled
endpoint, signed HMAC-SHA256 with the endpoint's secret — **returned once in this response**.
https URLs with public hostnames only; at most 5 endpoints.

#### Request body

`application/json` · required

| Field | Type | Description |
| --- | --- | --- |
| `url` **required** | `string<uri>` |  _(maxLength `512`)_ |

#### Responses

| Status | Body | Meaning |
| --- | --- | --- |
| `201` | `object` | Created; `endpoint.secret` is present ONLY here. |
| `400` | — | Invalid or unsafe URL. |
| `401` | `Error` | Missing, malformed or unknown API key. |
| `409` | — | Endpoint limit reached. |

**`201` response body**

| Field | Type | Description |
| --- | --- | --- |
| `endpoint` | `object` | — |
| `endpoint.id` | `integer` | — |
| `endpoint.url` | `string` | — |
| `endpoint.enabled` | `boolean` | — |
| `endpoint.created_at` | `string<date-time>` | — |
| `endpoint.secret_hint` | `string` | First 8 characters of the signing secret. |
| `endpoint.secret` | `string` | Full signing secret — present ONLY on create/regenerate. |

```json
{
  "endpoint": {
    "id": 1,
    "url": "string",
    "enabled": true,
    "created_at": "2026-08-31T09:15:00.000Z",
    "secret_hint": "string",
    "secret": "string"
  }
}
```

#### Example request

```bash
curl -X POST 'https://api.cryptoinfra.build/v1/developer/webhooks' \
  -H 'Authorization: Bearer ck_live_your_key' \
  -H 'Content-Type: application/json' \
  -d '{
  "url": "https://example.com"
}'
```

## POST /v1/developer/webhooks/{id}

**Enable or disable an endpoint**  ·  _Auth: bearer API key_  ·  `operationId: toggleWebhookEndpoint`

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | `integer` | yes | — |

#### Request body

`application/json` · required

| Field | Type | Description |
| --- | --- | --- |
| `enabled` **required** | `boolean` | — |

#### Responses

| Status | Body | Meaning |
| --- | --- | --- |
| `200` | — | Updated. |
| `404` | — | No such endpoint. |

#### Example request

```bash
curl -X POST 'https://api.cryptoinfra.build/v1/developer/webhooks/1' \
  -H 'Authorization: Bearer ck_live_your_key' \
  -H 'Content-Type: application/json' \
  -d '{
  "enabled": true
}'
```

## DELETE /v1/developer/webhooks/{id}

**Delete an endpoint**  ·  _Auth: bearer API key_  ·  `operationId: deleteWebhookEndpoint`

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | `integer` | yes | — |

#### Responses

| Status | Body | Meaning |
| --- | --- | --- |
| `200` | — | Deleted (delivery history is kept |
| `404` | — | No such endpoint. |

#### Example request

```bash
curl -X DELETE 'https://api.cryptoinfra.build/v1/developer/webhooks/1' \
  -H 'Authorization: Bearer ck_live_your_key'
```

## POST /v1/developer/webhooks/{id}/regenerate

**Regenerate an endpoint's signing secret**  ·  _Auth: bearer API key_  ·  `operationId: regenerateWebhookSecret`

The new secret is returned once; the old one stops verifying immediately.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | `integer` | yes | — |

#### Responses

| Status | Body | Meaning |
| --- | --- | --- |
| `200` | — | New secret in `endpoint.secret` (only here). |
| `404` | — | No such endpoint. |

#### Example request

```bash
curl -X POST 'https://api.cryptoinfra.build/v1/developer/webhooks/1/regenerate' \
  -H 'Authorization: Bearer ck_live_your_key'
```

## POST /v1/developer/webhooks/{id}/test

**Send a signed test event**  ·  _Auth: bearer API key_  ·  `operationId: testWebhookEndpoint`

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | `integer` | yes | — |

#### Request body

`application/json` · optional

| Field | Type | Description |
| --- | --- | --- |
| `event_type` | `string` | `payment.received` is deprecated — payment links are retired and the event is no longer emitted; it is still accepted here so an older client's test-fire does not fail. _(one of `webhook.test`, `deposit.credited`, `withdrawal.confirmed`, `withdrawal.failed`, `card.kyc`, `card.status`, `card.topup`, `card.withdraw`, `card.transaction`, `card.wallet_otp`, `payment.received`)_ |

#### Responses

| Status | Body | Meaning |
| --- | --- | --- |
| `202` | — | Queued through the real dispatcher. |
| `404` | — | No such enabled endpoint. |

#### Example request

```bash
curl -X POST 'https://api.cryptoinfra.build/v1/developer/webhooks/1/test' \
  -H 'Authorization: Bearer ck_live_your_key' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

## GET /v1/developer/logs

**Your recent API requests**  ·  _Auth: bearer API key_  ·  `operationId: listApiLogs`

Method, route, status and duration of your last calls (kept 14 days; no bodies, no query strings).

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `limit` | query | `integer` | no | — _(min `1`; max `200`)_ |

#### Responses

| Status | Body | Meaning |
| --- | --- | --- |
| `200` | `object` | The request log. |
| `401` | `Error` | Missing, malformed or unknown API key. |

**`200` response body**

| Field | Type | Description |
| --- | --- | --- |
| `requests` | `object[]` | — |
| `requests[].id` | `integer` | — |
| `requests[].method` | `string` | — |
| `requests[].path` | `string` | — |
| `requests[].status` | `integer` | — |
| `requests[].duration_ms` | `integer` | — |
| `requests[].created_at` | `string<date-time>` | — |

```json
{
  "requests": [
    {
      "id": 1,
      "method": "string",
      "path": "string",
      "status": 1,
      "duration_ms": 1,
      "created_at": "2026-08-31T09:15:00.000Z"
    }
  ]
}
```

#### Example request

```bash
curl -X GET 'https://api.cryptoinfra.build/v1/developer/logs' \
  -H 'Authorization: Bearer ck_live_your_key'
```

## GET /v1/events

**Live event stream (Server-Sent Events)**  ·  _Auth: bearer API key_  ·  `operationId: eventStream`

A `text/event-stream` of your account's activity, for a dashboard that
updates without refreshing. Same key as every other route. Each message
is one JSON object `{ type, ts, data }`; `type` is one of
`deposit.credited` (data: depositId, userExternalId, chain, assetId,
symbol, amount, txid), `withdrawal.updated` (withdrawalId, status, chain,
assetId, symbol, amount, txid) or `card.order.updated` (orderId, kind,
status, providerStatus, userExternalId). A comment line is sent every
25 seconds as a heartbeat.

Best-effort and not a webhook: a dropped connection loses what happened
while it was down, and nothing is replayed. It is a hint to go and read
the record; the poll endpoints stay the truth.

#### Responses

| Status | Body | Meaning |
| --- | --- | --- |
| `200` | — | The stream. Stays open for the life of the connection. |
| `401` | `Error` | Missing, malformed or unknown API key. |
| `503` | `Error` | `live_events_unavailable` — no event hub on this deployment. |

#### Example request

```bash
curl -X GET 'https://api.cryptoinfra.build/v1/events' \
  -H 'Authorization: Bearer ck_live_your_key'
```
