# Inter X Public API

Organisation API for Know Your Entity (KYE), Know Your Transaction (KYT), Address Prescreening, Wallet Holdings, and USDT Blacklist checks.

- **In-app docs:** [/docs/api](https://theinterx.com/docs/api) (OpenAPI explorer + quick start)
- **Base URL:** `https://theinterx.com/api/v1`
- **Auth:** Organisation API key (`Authorization: Bearer ix_live_…` or `X-Api-Key`)
- **OpenAPI:** [`openapi.yaml`](https://theinterx.com/docs/api/openapi.yaml) (also at `/docs/api/openapi.yaml`)
- **Credits:** Same as the dashboard — KYT create, Address Prescreening create, and KYE entity profile cost credits; search/risk/history do not. Failed upstream calls refund the charge.

## Create an API key

1. Sign in as an organisation **owner**
2. Open **Organisation**
3. Under **API keys**, enter a name and click **Create API key**
4. Copy the key immediately — it is shown once

Revoke unused keys from the same page.

## Authentication

```bash
export INTERX_API_KEY='ix_live_xxxxxxxx'
export INTERX_API_BASE='https://theinterx.com/api/v1'

curl -sS "$INTERX_API_BASE/organisation" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Accept: application/json"
```

Successful responses use:

```json
{
  "data": {},
  "meta": {}
}
```

Errors use:

```json
{
  "message": "Human readable error",
  "code": "insufficient_credits"
}
```

Common codes: `unauthenticated`, `insufficient_credits`, `not_found`, `upstream_error`, plus Laravel validation (`422`).

---

## Organisation

### Get organisation + credit balance

```bash
curl -sS "$INTERX_API_BASE/organisation" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Accept: application/json"
```

---

## Address Prescreening

Screen a destination address **before sending** (no transaction hash). Separate from KYT.

Costs **1 credit** on create (configurable via `INTERX_PRESCREEN_CREDIT_COST`). Poll until `meta.ready` is `true`.

If the same chain/asset/address/amount was already screened to completion on Inter X
(any organisation), create returns the stored result with `meta.reused: true` and does
**not** call Arrel again. Credits are still charged.

### Create a prescreen

```bash
curl -sS -X POST "$INTERX_API_BASE/address-prescreening" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "blockchain": "Ethereum",
    "currency": "USDT",
    "target_address": "0x9b5d7B27d547f99906AC6AEdF8f180dFD4E07A68",
    "amount": 100.5
  }'
```

### Poll until ready

```bash
EXTERNAL_ID='prescreen-provider-id'

curl -sS "$INTERX_API_BASE/address-prescreening/$EXTERNAL_ID/poll" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Accept: application/json"
```

---

## Know Your Transaction (KYT)

Screens an **actual transaction** (requires `tx_id`). Costs **1 credit** on create. Poll until `meta.ready` is `true`.

If the same chain/asset/address/`tx_id` was already screened to completion on Inter X
(any organisation), create returns the stored result with `meta.reused: true` and does
**not** call Arrel again. Credits are still charged.

### Create a check

```bash
curl -sS -X POST "$INTERX_API_BASE/kyt" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "blockchain": "Bitcoin",
    "currency": "BTC",
    "target_address": "bc1qexample",
    "tx_id": "txid_example"
  }'
```

Response highlights:

- `data.id` — Inter X check id (stored in history)
- `data.external_id` — provider id (use for poll/show)
- `data.state` — `pending` | `processing` | `stalled` | `complete` | `failed`
- `data.result.pass`, `data.result.alert_level`, alerts / exposures
- `meta.credit_balance`, `meta.credits_charged`

### Poll until ready

```bash
EXTERNAL_ID='kyt-provider-id'

curl -sS "$INTERX_API_BASE/kyt/$EXTERNAL_ID/poll" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Accept: application/json"
```

When `meta.ready` is `true`, the PDF report is available upstream and screening is complete. Keep polling every ~10s while `ready` is `false`.

### Fetch current KYT status

```bash
curl -sS "$INTERX_API_BASE/kyt/$EXTERNAL_ID" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Accept: application/json"
```

---

## Know Your Entity (KYE)

Search and risk index are **free**. Entity profile costs **1 credit**.

### Search entities

```bash
curl -sS "$INTERX_API_BASE/kye/search?query=binance&limit=10" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Accept: application/json"
```

`query` is the search text (entity name, alias, etc.). Hits include `entity_id` for the profile call.

### Risk index (browse / filter)

```bash
curl -sS "$INTERX_API_BASE/kye/risk?page=1&limit=20&risk_level=high" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Accept: application/json"
```

Optional query params: `page`, `limit`, `letter`, `query`, `risk_level`.

### Entity profile (charged)

The **entity is path `{id}`** (from search/risk). Uses **POST** so clients and proxies do not accidentally spend credits on retries or prefetch.

```bash
ENTITY_ID=123

curl -sS -X POST "$INTERX_API_BASE/kye/entities/$ENTITY_ID" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"search_term":"binance"}'
```

Optional JSON body field: `search_term` — stored on the history row for audit only; it does not select the entity.

Response includes mapped `entity`, `risk`, `aliases`, `executives`, `licenses`, `locations`, `media`, plus `meta.credit_balance`.

---

## History

Lists stored KYE / KYT / Address Prescreen checks for the organisation, newest first.

`limit` is optional (default 50, max 100). Use `page` to fetch older checks beyond the first page.

```bash
curl -sS "$INTERX_API_BASE/history?type=all&limit=50&page=1" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Accept: application/json"

# Next page
curl -sS "$INTERX_API_BASE/history?type=all&limit=50&page=2" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Accept: application/json"
```

`type`: `all` | `kyt` | `prescreen` | `kye`

Response `meta.pagination`: `{ page, limit, total, pages }`.

### Get stored check detail (free)

Use the Inter X check `id` from list rows — not the provider `external_id`:

```bash
CHECK_ID=123

curl -sS "$INTERX_API_BASE/history/kyt/$CHECK_ID" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Accept: application/json"

curl -sS "$INTERX_API_BASE/history/kye/$CHECK_ID" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Accept: application/json"
```

Path `type`: `kyt` | `prescreen` | `kye`. Returns the full stored result without spending credits or calling upstream. Especially useful for KYE history replay.

---

## Wallet Holdings

Look up token balances for an EVM, Solana, or Tron address. **Free** — does not spend credits.

```bash
curl -sS -X POST "$INTERX_API_BASE/wallet-holdings" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"
  }'
```

Optional `chains` array limits lookup (e.g. `["mainnet", "polygon"]`). Supported ids: `mainnet`, `bsc`, `polygon`, `optimism`, `base`, `unichain`, `avalanche`, `arbitrum-one`, `solana`, `tron`.

---

## USDT Blacklist

Check whether an address is frozen on Tether's official USDT contract per chain. Reads directly from on-chain contracts — not third-party checkers. **Free** — does not spend credits. Requires an active subscription.

Defaults to `ethereum` and `tron` when `chains` is omitted. A failed, unsupported, or inconclusive check is never reported as `clean`.

```bash
curl -sS -X POST "$INTERX_API_BASE/usdt-blacklist" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"
  }'
```

Optional `chains` array limits lookup (e.g. `["ethereum", "tron", "solana"]`). Supported ids: `ethereum`, `avalanche`, `celo`, `kava`, `kaia`, `tron`, `solana`, `ton`, `near`, `aptos`, `tezos`, `polkadot-assethub`, `liquid`.

Response `data.checks[]` includes per-chain `status`: `blacklisted`, `clean`, `no-account`, `unsupported`, or `error`.

---

## Rate limits

Same as the dashboard UI:

| Route group | Limit |
|-------------|-------|
| Default `/api/v1/*` | 60 / minute |
| `POST /wallet-holdings` | 20 / minute |
| `POST /usdt-blacklist` | 20 / minute |
| `POST /kyt` | 20 / minute |
| `POST /address-prescreening` | 20 / minute |
| `POST /kye/entities/{id}` | 20 / minute |

---

## Typical KYT flow

```bash
# 1) Create
CREATE=$(curl -sS -X POST "$INTERX_API_BASE/kyt" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"blockchain":"Bitcoin","currency":"BTC","target_address":"bc1q…","tx_id":"…"}')

EXTERNAL_ID=$(echo "$CREATE" | jq -r '.data.external_id')

# 2) Poll
while true; do
  POLL=$(curl -sS "$INTERX_API_BASE/kyt/$EXTERNAL_ID/poll" \
    -H "Authorization: Bearer $INTERX_API_KEY")
  READY=$(echo "$POLL" | jq -r '.meta.ready')
  echo "$POLL" | jq '{state: .data.state, ready: .meta.ready, pass: .data.result.pass}'
  [ "$READY" = "true" ] && break
  sleep 10
done
```

## Typical KYE flow

```bash
# 1) Free search
HITS=$(curl -sS "$INTERX_API_BASE/kye/search?query=kraken&limit=5" \
  -H "Authorization: Bearer $INTERX_API_KEY")
ENTITY_ID=$(echo "$HITS" | jq -r '.data[0].entity_id')

# 2) Charged profile
curl -sS -X POST "$INTERX_API_BASE/kye/entities/$ENTITY_ID" \
  -H "Authorization: Bearer $INTERX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}' | jq .
```
