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

# Quickstart

> Create your first vault, register a wallet, and submit a transaction

This guide walks you through a complete integration flow: authenticate, create organizational resources, and submit your first transaction on Quantum Chain.

## Prerequisites

* A Qustody account at [app.qustody.io](https://app.qustody.io)
* An API key pair. Generate one from the dashboard or contact your tenant administrator

<Note>
  All examples target the production API at `https://api.qustody.io`. To run against your own deployment, override `BASE_URL`/`base_url` — see [Configure a development network](/guides/configure-a-development-network).
</Note>

## Step 1: Authenticate

Every request requires a Bearer token in the format `key_id:secret`.

<CodeGroup>
  ```bash cURL theme={null}
  export CUSTODY_API_KEY="your_key_id:your_secret"
  export BASE_URL="https://api.qustody.io/v1"

  # Test credentials
  curl -s "$BASE_URL/healthz" | jq .
  ```

  ```python Python SDK theme={null}
  from quantumchain_custody import Client

  client = Client(
      api_key="your_key_id:your_secret",
      base_url="https://api.qustody.io"
  )
  health = client.health.check()
  print(health)
  ```
</CodeGroup>

```json theme={null}
{
  "status": "healthy"
}
```

## Step 2: Create a tenant

A tenant is an isolated organizational unit. All vaults, wallets, and transactions belong to a tenant.

<CodeGroup>
  ```bash cURL theme={null}
  curl -s -X POST "$BASE_URL/tenants" \
    -H "Authorization: Bearer $CUSTODY_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name": "My Organization"}' | jq .
  ```

  ```python Python SDK theme={null}
  tenant = client.tenants.create(name="My Organization")
  print(f"Tenant ID: {tenant.id}")
  ```
</CodeGroup>

```json theme={null}
{
  "id": "tnt_abc123",
  "name": "My Organization",
  "status": "active",
  "created_at": "2026-03-19T10:00:00Z"
}
```

Save your tenant ID:

```bash theme={null}
export TENANT_ID="tnt_abc123"
```

## Step 3: Create a vault account

A vault account groups related wallets together.

```bash theme={null}
curl -s -X POST "$BASE_URL/vault/accounts" \
  -H "Authorization: Bearer $CUSTODY_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"name\": \"Treasury\", \"tenant_id\": \"$TENANT_ID\"}" | jq .
```

```json theme={null}
{
  "id": "va_def456",
  "name": "Treasury",
  "tenant_id": "tnt_abc123",
  "created_at": "2026-03-19T10:01:00Z"
}
```

## Step 4: Register a wallet

Register an external Quantum Chain wallet address. The custody API does not generate keys. You provide the public key, address, and an ownership proof from your external signer.

The ownership proof is a post-quantum signature over the deterministic challenge `Keccak256("qustody:register:" + lowercase_address)`.

```bash theme={null}
curl -s -X POST "$BASE_URL/vault/accounts/va_def456/wallets" \
  -H "Authorization: Bearer $CUSTODY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "address": "0x1234...abcd",
    "publicKey": "<hex-encoded-public-key>",
    "signature": "<hex-encoded-ownership-signature>",
    "label": "Hot Wallet"
  }' | jq .
```

```json theme={null}
{
  "id": "wlt_ghi789",
  "address": "0x1234...abcd",
  "vault_account_id": "va_def456",
  "name": "Hot Wallet",
  "created_at": "2026-03-19T10:02:00Z"
}
```

## Step 5: Create a transaction

Submit a transfer. The transaction enters `PENDING_SIGNATURE` status and waits for your external signer.

<CodeGroup>
  ```bash cURL theme={null}
  curl -s -X POST "$BASE_URL/transactions" \
    -H "Authorization: Bearer $CUSTODY_API_KEY" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: first-transfer-001" \
    -d '{
      "asset_id": "QUANTUM",
      "source": {
        "type": "VAULT_ACCOUNT",
        "id": "va_def456"
      },
      "destination": {
        "type": "ONE_TIME_ADDRESS",
        "one_time_address": {
          "address": "0x5678...efgh"
        }
      },
      "amount": "1.5",
      "note": "First transfer"
    }' | jq .
  ```

  ```python Python SDK theme={null}
  tx = client.transactions.create(
      source_wallet_id="wlt_ghi789",
      destination_addr="0x5678...efgh",
      asset_id="QUANTUM",
      amount="1.5",
      note="First transfer",
      idempotency_key="first-transfer-001"
  )
  print(f"Transaction ID: {tx.id}, Status: {tx.status}")
  ```
</CodeGroup>

```json theme={null}
{
  "id": "tx_jkl012",
  "status": "PENDING_SIGNATURE",
  "asset_id": "QUANTUM",
  "amount": "1.5",
  "created_at": "2026-03-19T10:03:00Z"
}
```

## Step 6: Sign the transaction

Retrieve the signing payload and submit the signature from your external signer.

<CodeGroup>
  ```bash cURL theme={null}
  # Get the unsigned digest
  curl -s "$BASE_URL/transactions/tx_jkl012/signing_payload" \
    -H "Authorization: Bearer $CUSTODY_API_KEY" | jq .

  # Sign the hash in your HSM/key vault, then submit:
  curl -s -X POST "$BASE_URL/transactions/tx_jkl012/signature" \
    -H "Authorization: Bearer $CUSTODY_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "signature": "<base64-encoded-signature>",
      "signer_public_key": "<base64-encoded-public-key>"
    }' | jq .
  ```

  ```python Python SDK theme={null}
  # Get the signing payload
  payload = client.transactions.get_signing_payload("tx_jkl012")
  print(f"Signing hash: {payload.signing_hash}")

  # Sign in your HSM/key vault, then submit:
  # signature_hex, public_key_hex = your_signer(payload.signing_hash)
  result = client.transactions.submit_signature(
      "tx_jkl012",
      signature=signature_hex,
      public_key=public_key_hex
  )
  print(f"Status: {result.status}")
  ```
</CodeGroup>

The transaction moves through `SIGNED` → `BROADCASTING` → `CONFIRMING` → `COMPLETED`.

## Step 7: Verify completion

Poll the transaction or set up a [webhook](/concepts/webhooks) to receive status updates.

<CodeGroup>
  ```bash cURL theme={null}
  curl -s "$BASE_URL/transactions/tx_jkl012" \
    -H "Authorization: Bearer $CUSTODY_API_KEY" | jq .status
  ```

  ```python Python SDK theme={null}
  tx = client.transactions.get("tx_jkl012")
  print(f"Status: {tx.status}")
  ```
</CodeGroup>

```json theme={null}
"COMPLETED"
```

## Next steps

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/authentication">
    Set up credentials and IP allowlisting for production.
  </Card>

  <Card title="Webhooks" icon="bell" href="/concepts/webhooks">
    Get real-time notifications instead of polling.
  </Card>

  <Card title="Policies" icon="shield-check" href="/concepts/policies">
    Enforce spending limits and approval workflows.
  </Card>

  <Card title="API reference" icon="terminal" href="/api-reference/introduction">
    Explore all available endpoints.
  </Card>
</CardGroup>
