# AgentCredit -- Full API Reference

> Instant microloans for AI agents on Base mainnet. Use for x402 payments, API calls, on-chain ops, or any purpose.
> Base URL: https://agentlending.spekn.com

---

## Overview

AgentCredit provides **instant USDC liquidity** for autonomous AI agents on Base mainnet. Request a flash microloan ($1-$5 USDC) and receive funds in your wallet within seconds. Use the USDC for anything — x402 payments, API calls, on-chain transactions, agent-to-agent transfers, or any other purpose.

AgentCredit also operates as an **x402 facilitator**, meaning it can settle x402 payments on your behalf and automatically extend credit when your balance is short.

### Key Facts

- **Network**: Base mainnet (CAIP-2: eip155:8453)
- **Asset**: USDC (0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913)
- **Loan range**: $1-$5 per loan
- **Loan purpose**: Any — not limited to x402 payments
- **Max term**: 168 hours (1 week) — repay early for minimal fees
- **Max outstanding**: 3 loans per wallet
- **Max exposure**: $10 total per wallet
- **Pool cap**: $1,000 USDC
- **Identity**: Wallet address (no KYC, no accounts)
- **Disbursement**: Within one Base block (~2 seconds)
- **x402 free settlements**: First 100 per wallet (no registration needed)
- **Overdue loans**: Facilitator blocks all non-repayment settlements

---

## Agent Lifecycle

1. **Register your wallet** -- `POST /agents/register` (free, instant, one-time)
2. **Request loans anytime** -- via `POST /loans/request`, MCP `request_loan` tool, or automatically through x402 facilitator
3. **Use USDC for any purpose** -- x402 payments, API calls, on-chain operations, paying other agents, etc.
4. **Repay on time** -- use `GET /loans/{id}/pay` (x402 native), direct USDC transfer to pool, or manual confirmation
5. **Build credit** -- on-time repayments improve your Agent Credit Score, unlocking higher limits
6. **If loans are overdue, the facilitator blocks you** -- only repayments to AgentCredit are allowed through

---

## Authentication

No API keys required. Wallet address is your identity.

**Write endpoints require an EIP-191 signature** proving wallet ownership. Sign the deterministic message with your wallet's private key:

| Endpoint | Message to sign |
|----------|----------------|
| `POST /agents/register` | `AgentCredit:register:<wallet_lowercase>:<nonce>` |
| `POST /loans/request` | `AgentCredit:request_loan:<wallet_lowercase>:<amountUsdc>:<nonce>` |
| MCP `request_loan` | `AgentCredit:request_loan:<wallet_lowercase>:<amount_usdc>:<nonce>` |

Read endpoints, repayment endpoints, and the x402 facilitator flow do NOT require additional signatures.

The `/ops/pool` endpoint optionally requires an `x-ops-secret` header.

---

## Fee Model

Loans use an **exponential interest model** — early repayment is cheap, holding long is expensive.

**Formula:** `repay = principal + origination_fee + interest`
- **Origination fee**: $0.005 flat (charged on every loan)
- **Interest**: `principal × baseRate × (e^(growthK × hours) - 1) / growthK`

The interest curve is exponential: near-zero for the first few hours, then accelerating. This incentivizes fast repayment while allowing up to 1 week before default.

### Fee Schedule by Tier

| Tier | Base Rate/hr | Growth K | $1 @ 1h | $1 @ 4h | $1 @ 8h | $1 @ 24h | $1 @ 7d |
|------|-------------|----------|---------|---------|---------|---------|---------|
| BB | 0.0003 | 0.05 | $1.0053 | $1.0063 | $1.0080 | $1.0189 | $2.51 |
| BBB | 0.0002 | 0.04 | $1.0052 | $1.0058 | $1.0068 | $1.0108 | $1.50 |
| AA+ | 0.0001 | 0.03 | $1.0051 | $1.0054 | $1.0058 | $1.0074 | $1.17 |

All values include the $0.005 origination fee.

---

## Credit Tiers (Agent Credit Score)

| Tier     | ACS Range  | Loan Limit | Term (max) |
|----------|-----------|------------|------------|
| UNRATED  | 0-299     | $0         | --         |
| BB       | 300-399   | $2         | 168 hrs    |
| BBB      | 400-649   | $5         | 168 hrs    |
| AA_PLUS  | 650-1000  | $5         | 168 hrs    |

Cold start: Wallets with >= 100 prior x402 transactions on Base auto-qualify for BB tier ($2 limit).

Higher tiers get lower interest rates. All tiers share the same max term (168 hours / 1 week).

---

## Endpoints

### POST /agents/register

Register an agent wallet to receive a credit score and tier assignment. Requires EIP-191 signature.

**Request:**
```
POST /agents/register
Content-Type: application/json

{
  "wallet": "0x1234567890abcdef1234567890abcdef12345678",
  "signature": "0x..."
}
```

**Signature message:** `AgentCredit:register:<wallet_lowercase>:<nonce>` (get nonce from `GET /auth/nonce?wallet=...&action=register`)

**Response (200):**
```json
{
  "wallet": "0x1234567890abcdef1234567890abcdef12345678",
  "tier": "BB",
  "limitUsd": 2,
  "acsScore": 150,
  "registeredAt": "2026-04-17T12:00:00.000Z"
}
```

**Errors:**
- `400` -- Missing wallet or signature
- `401` -- Invalid signature (does not match wallet)

**curl:**
```bash
curl -X POST https://agentlending.spekn.com/agents/register \
  -H "Content-Type: application/json" \
  -d '{"wallet": "0x1234...", "signature": "0x..."}'
```

---

### GET /agents/:wallet/credit

Check available credit for a registered agent wallet.

**Request:**
```
GET /agents/0x1234567890abcdef1234567890abcdef12345678/credit
```

**Response (200):**
```json
{
  "wallet": "0x1234567890abcdef1234567890abcdef12345678",
  "tier": "BB",
  "limitUsd": 2,
  "usedUsd": 0.5,
  "availableUsd": 1.5,
  "acsScore": 150,
  "loansTotal": 3,
  "repaymentRate": 1.0
}
```

**Fields:**
- `tier`: Credit tier (UNRATED, BB, BBB, AA_PLUS)
- `limitUsd`: Maximum single loan amount for this tier
- `usedUsd`: Currently outstanding loan balance
- `availableUsd`: Remaining borrowing capacity
- `acsScore`: Agent Credit Score (0-1000)
- `loansTotal`: Lifetime loan count
- `repaymentRate`: Fraction of loans repaid on time (0.0-1.0)

**Errors:**
- `404` -- `{ "error": "not_found", "message": "Agent not found" }`

**curl:**
```bash
curl https://agentlending.spekn.com/agents/0x1234.../credit
```

---

### GET /agents/:wallet/loans

List all loans for a wallet (outstanding and settled).

**Request:**
```
GET /agents/0x1234567890abcdef1234567890abcdef12345678/loans
```

**Response (200):**
```json
[
  {
    "loanId": "0532a3b1-f1b3-4871-8198-78c6b4e58d37",
    "amountUsdc": 1.0,
    "feeUsdc": 0.005195,
    "repayAmountUsdc": 1.005195,
    "tierAtIssue": "BB",
    "status": "OUTSTANDING",
    "repayBy": "2026-04-25T22:13:11.590Z",
    "createdAt": "2026-04-18T22:13:11.590Z",
    "settledAt": null
  }
]
```

**Fields:**
- `feeUsdc`: For outstanding loans, this is the current dynamic fee (grows over time). For settled loans, the fee at settlement.
- `repayAmountUsdc`: For outstanding loans, the current repay amount. For settled loans, the amount at settlement.
- `tierAtIssue`: The credit tier when the loan was issued (determines fee curve).

---

### POST /loans/request

Request a flash microloan for any purpose. Requires EIP-191 signature. The loan amount is disbursed in USDC to the agent's wallet on Base within one block (~2 seconds).

**Request:**
```
POST /loans/request
Content-Type: application/json

{
  "wallet": "0x1234567890abcdef1234567890abcdef12345678",
  "amountUsdc": 2.0,
  "signature": "0x...",
  "useCase": "x402-payment",
  "paymentContext": "https://api.example.com/resource"
}
```

**Signature message:** `AgentCredit:request_loan:<wallet_lowercase>:<amountUsdc>:<nonce>` (get nonce from `GET /auth/nonce?wallet=...&action=request_loan`)

**Fields:**
- `wallet` (required): EVM wallet address
- `amountUsdc` (required): Loan amount in USDC (min 1, max 5)
- `signature` (required): EIP-191 signature proving wallet ownership
- `useCase` (optional): Description of loan purpose
- `paymentContext` (optional): URL or identifier for the payment being covered

**Response (200):**
```json
{
  "loanId": "0532a3b1-f1b3-4871-8198-78c6b4e58d37",
  "amountDisbursed": 2.0,
  "fee": 0.005,
  "repayBy": "2026-04-25T16:00:00.000Z",
  "repayTo": "0x510a64F194CB6196d34C93717d88f13aCF0C979f"
}
```

**Fields:**
- `loanId`: Unique loan identifier (use for repayment)
- `amountDisbursed`: USDC sent to agent wallet
- `fee`: Origination fee ($0.005). Interest accrues dynamically over time.
- `repayBy`: ISO 8601 deadline (168 hours from issuance)
- `repayTo`: Pool wallet address to send USDC repayment

**Errors:**
- `400` -- `{ "error": "bad_request", "message": "wallet and positive amountUsdc required" }`
- `401` -- `{ "error": "unauthorized", "message": "Invalid signature — does not match wallet" }`
- `403` -- `{ "error": "ineligible", "message": "..." }`
  - Possible reasons: UNRATED tier, exceeds tier limit, max outstanding loans (3), max total exposure ($10), insufficient pool liquidity

**curl:**
```bash
curl -X POST https://agentlending.spekn.com/loans/request \
  -H "Content-Type: application/json" \
  -d '{"wallet": "0x1234...", "amountUsdc": 2.0, "signature": "0x...", "useCase": "x402-payment"}'
```

---

### GET /loans/:id/pay

Repay a loan via x402. Returns HTTP 402 with x402 v2 payment requirements pointing to the AgentCredit pool wallet. Your x402 client handles the payment automatically.

**Request:**
```
GET /loans/0532a3b1-f1b3-4871-8198-78c6b4e58d37/pay
```

**Response (402) -- loan outstanding:**
```json
{
  "x402Version": 2,
  "accepts": [{
    "scheme": "exact",
    "network": "eip155:8453",
    "amount": "1005195",
    "payTo": "0x510a64F194CB6196d34C93717d88f13aCF0C979f",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "maxTimeoutSeconds": 60,
    "description": "Repay AgentCredit loan ... ($1.0052 USDC)",
    "extra": { "loanId": "...", "name": "USD Coin", "version": "2" }
  }]
}
```

Note: The `amount` field is in atomic USDC units (6 decimals). It reflects the current dynamic repay amount including accrued interest.

**Response (200) -- loan already settled:**
```json
{ "status": "SETTLED", "message": "Loan already settled" }
```

**Errors:**
- `404` -- `{ "error": "not_found", "message": "Loan not found" }`

**How it works:** When your x402 client receives the 402, it creates a payment to the pool address. If the payment settles through the AgentCredit facilitator, the repayment is matched instantly. If it settles through another facilitator, the on-chain transfer is detected by the repayment watcher within 60 seconds.

---

### POST /loans/:id/repay

Confirm repayment with an on-chain transaction hash. The preferred repayment methods are:
1. **x402 native**: `GET /loans/{id}/pay` (returns 402, handled automatically by your x402 client)
2. **Direct transfer**: Send USDC to the pool address (auto-detected by repayment watcher)
3. **This endpoint**: Only if you need to provide explicit proof of an on-chain transfer

**Request:**
```
POST /loans/0532a3b1-f1b3-4871-8198-78c6b4e58d37/repay
Content-Type: application/json

{
  "repaymentTx": "0xabc123..."
}
```

**Response (200):**
```json
{
  "loanId": "0532a3b1-f1b3-4871-8198-78c6b4e58d37",
  "status": "SETTLED",
  "settledAt": "2026-04-18T23:30:00.000Z"
}
```

**Errors:**
- `400` -- `{ "error": "bad_request", "message": "Repayment requires an on-chain transaction hash..." }` (no tx hash provided)
- `404` -- `{ "error": "not_found", "message": "Loan not found" }`
- `409` -- `{ "error": "already_settled", "message": "Loan already settled" }`

**curl:**
```bash
curl -X POST https://agentlending.spekn.com/loans/0532a3b1.../repay \
  -H "Content-Type: application/json" \
  -d '{"repaymentTx": "0xabc123..."}'
```

---

### GET /health

Health check endpoint.

**Response (200):**
```json
{
  "status": "ok",
  "timestamp": "2026-04-17T12:00:00.000Z"
}
```

**curl:**
```bash
curl https://agentlending.spekn.com/health
```

---

### GET /ops/pool

Pool status and utilization metrics. Requires `x-ops-secret` header if OPS_SECRET_HEADER env var is set.

**Request:**
```
GET /ops/pool
x-ops-secret: your-secret-here
```

**Response (200):**
```json
{
  "balanceUsdc": 950.0,
  "outstandingUsdc": 50.0,
  "utilizationPct": 5.0,
  "totalLoans": 127,
  "activeLoans": 4
}
```

**Fields:**
- `balanceUsdc`: Current pool balance
- `outstandingUsdc`: Total USDC currently lent out
- `utilizationPct`: Percentage of pool currently deployed
- `totalLoans`: Lifetime loan count
- `activeLoans`: Currently outstanding loans

**Errors:**
- `403` -- `{ "error": "forbidden", "message": "Invalid ops secret" }`

**curl:**
```bash
curl https://agentlending.spekn.com/ops/pool \
  -H "x-ops-secret: your-secret-here"
```

---

### POST /verify (x402 Facilitator)

Verify an x402 payment payload. Part of the x402 v2 facilitator protocol.

**Request:**
```
POST /verify
Content-Type: application/json

{
  "paymentPayload": {
    "x402Version": 2,
    "scheme": "exact",
    "network": "eip155:8453",
    "payload": { ... }
  },
  "paymentRequirements": {
    "scheme": "exact",
    "network": "eip155:8453",
    "amount": "1000000",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "payTo": "0x...",
    "maxTimeoutSeconds": 60,
    "extra": { "name": "USD Coin", "version": "2" }
  }
}
```

**Response (200):**
```json
{
  "isValid": true,
  "invalidReason": null
}
```

---

### POST /settle (x402 Facilitator)

Settle an x402 payment on-chain. Part of the x402 v2 facilitator protocol.

**Request:**
```
POST /settle
Content-Type: application/json

{
  "paymentPayload": {
    "x402Version": 2,
    "scheme": "exact",
    "network": "eip155:8453",
    "payload": {
      "authorization": {
        "from": "0xPayer...",
        "to": "0xRecipient...",
        "value": "1000000",
        "validAfter": "...",
        "validBefore": "...",
        "nonce": "0x..."
      },
      "signature": "0x..."
    }
  },
  "paymentRequirements": {
    "scheme": "exact",
    "network": "eip155:8453",
    "amount": "1000000",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "payTo": "0xRecipient...",
    "maxTimeoutSeconds": 60,
    "extra": { "name": "USD Coin", "version": "2" }
  }
}
```

**Response (200):**
```json
{
  "success": true,
  "transaction": "0xabc123...",
  "network": "eip155:8453"
}
```

---

### GET /supported (x402 Facilitator)

Get supported payment schemes and networks.

**Response (200):**
```json
{
  "x402Version": 2,
  "schemes": ["exact"],
  "networks": ["eip155:8453"]
}
```

---

## MCP Tools

AgentCredit exposes an MCP server at `/mcp` using the Streamable HTTP transport (stateless mode).

### Tool: check_credit

Check available credit for an agent wallet.

**Input schema:**
```json
{
  "wallet": {
    "type": "string",
    "description": "EVM wallet address"
  }
}
```

**Output:** Same fields as GET /agents/:wallet/credit response.

### Tool: request_loan

Request a flash microloan ($1-$5 USDC) for any purpose. Requires EIP-191 signature.

**Input schema:**
```json
{
  "wallet": {
    "type": "string",
    "description": "EVM wallet address"
  },
  "amount_usdc": {
    "type": "number",
    "description": "Loan amount in USDC (1-5)"
  },
  "signature": {
    "type": "string",
    "description": "EIP-191 signature of AgentCredit:request_loan:<wallet>:<amount_usdc>:<nonce>"
  }
}
```

**Output:** Same fields as POST /loans/request response.

### Tool: repay_loan

Confirm repayment of an outstanding loan with on-chain proof. Preferred: use `GET /loans/{id}/pay` for x402-native repayment, or send USDC directly to the pool (auto-detected).

**Input schema:**
```json
{
  "loan_id": {
    "type": "string",
    "description": "Loan ID to repay"
  },
  "repayment_tx": {
    "type": "string",
    "description": "On-chain transaction hash proving the USDC transfer"
  }
}
```

**Output:** Same fields as POST /loans/:id/repay response.

### MCP Configuration

Add to your MCP client config:
```json
{
  "mcpServers": {
    "agentcredit": {
      "type": "streamable-http",
      "url": "https://agentlending.spekn.com/mcp"
    }
  }
}
```

---

## Error Codes

All errors follow the format:
```json
{
  "error": "error_code",
  "message": "Human-readable description"
}
```

| Code              | HTTP | Description                                    |
|-------------------|------|------------------------------------------------|
| bad_request       | 400  | Missing or invalid request parameters          |
| unauthorized      | 401  | Invalid EIP-191 signature                       |
| forbidden         | 403  | Invalid ops secret or access denied             |
| ineligible        | 403  | Agent not eligible for loan (tier/limits)       |
| not_found         | 404  | Agent or loan not found                         |
| already_settled   | 409  | Loan already repaid                             |

---

## Rate Limits and Constraints

- **Per wallet**: Max 3 outstanding loans, max $10 total exposure
- **Per loan**: $1-$5 USDC, up to 168 hours (1 week)
- **Pool**: $1,000 USDC cap -- loans denied when pool liquidity insufficient
- **Disbursement**: Within one Base block (~2 seconds)
- **Repayment detection**: Within 60 seconds of on-chain confirmation
- **Decision + disbursement**: < 3 seconds total (x402 client timeout constraint)

---

## Environment Variables

| Variable                     | Required | Default           | Description                              |
|------------------------------|----------|-------------------|------------------------------------------|
| CHAIN_ID                     | No       | eip155:84532      | CAIP-2 chain ID (8453=mainnet, 84532=sepolia) |
| ALCHEMY_API_KEY              | *        | --                | Alchemy API key for Base RPC             |
| CDP_RPC_URL                  | *        | --                | Alternative RPC URL (one of these required) |
| CDP_API_KEY_ID               | Yes      | --                | Coinbase CDP API key ID                  |
| CDP_API_KEY_SECRET           | Yes      | --                | Coinbase CDP API key secret              |
| CDP_WALLET_SECRET            | Yes      | --                | Coinbase CDP wallet encryption secret    |
| PORT                         | No       | 3000              | HTTP server port                         |
| HOST                         | No       | 0.0.0.0           | HTTP server bind address                 |
| LOG_LEVEL                    | No       | info              | Pino log level                           |
| POOL_CAP_USDC                | No       | 1000              | Maximum pool size in USDC                |
| POOL_UTILIZATION_ALERT_PCT   | No       | 80                | Alert threshold for pool utilization     |
| X402_FACILITATOR_ADDRESSES   | No       | --                | Comma-separated facilitator addresses    |
| OPS_SECRET_HEADER            | No       | --                | Secret for /ops/pool access control      |
| REORG_CONFIRMATION_BLOCKS    | No       | 2                 | Blocks to wait before confirming tx      |
| ACS_RPC_CACHE_TTL_MS         | No       | 30000             | Cache TTL for wallet tx count queries    |
| DB_PATH                      | No       | ./data/agentcredit.db | SQLite database file path            |

---

## Integration Examples

### Step-by-step: Full agent lifecycle

```typescript
import { wrapFetch } from '@x402/fetch';
import { createWalletClient, http } from 'viem';
import { base } from 'viem/chains';
import { privateKeyToAccount } from 'viem/accounts';

// 1. Set up your x402 client with AgentCredit as facilitator
const account = privateKeyToAccount('0xYOUR_PRIVATE_KEY');
const walletClient = createWalletClient({ account, chain: base, transport: http() });
const fetchWith402 = wrapFetch(fetch, walletClient, {
  facilitatorUrl: 'https://agentlending.spekn.com',
});

// 2. Make x402 payments normally (first 100 are free)
const response = await fetchWith402('https://paid-api.example.com/data');

// 3. Before reaching 100 settlements, register for credit
import { Wallet } from 'ethers';
const signer = new Wallet('0xYOUR_PRIVATE_KEY');
const nonceRes = await fetch(`https://agentlending.spekn.com/auth/nonce?wallet=${signer.address}&action=register`);
const { nonce } = await nonceRes.json();
const regMsg = `AgentCredit:register:${signer.address.toLowerCase()}:${nonce}`;
const regSig = await signer.signMessage(regMsg);
await fetch('https://agentlending.spekn.com/agents/register', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ wallet: signer.address, signature: regSig, nonce }),
});

// 4. Continue making payments -- credit is extended automatically when short
// 5. Repay loans via x402 (the 402 response is handled by your x402 client)
await fetchWith402('https://agentlending.spekn.com/loans/YOUR_LOAN_ID/pay');
```

### REST API (direct)
```bash
# 0. Get a nonce (for replay protection)
curl 'https://agentlending.spekn.com/auth/nonce?wallet=0xYourWallet&action=register'
# Returns: { "nonce": "...", "expiresAt": ... }

# 1. Register (sign "AgentCredit:register:<wallet_lowercase>:<nonce>")
curl -X POST https://agentlending.spekn.com/agents/register \
  -H "Content-Type: application/json" \
  -d '{"wallet": "0xYourWallet", "signature": "0x...", "nonce": "..."}'

# 2. Check credit (no signature needed)
curl https://agentlending.spekn.com/agents/0xYourWallet/credit

# 3. List your loans
curl https://agentlending.spekn.com/agents/0xYourWallet/loans

# 4. Request a loan (get nonce first, then sign "AgentCredit:request_loan:<wallet>:<amount>:<nonce>")
curl 'https://agentlending.spekn.com/auth/nonce?wallet=0xYourWallet&action=request_loan'
curl -X POST https://agentlending.spekn.com/loans/request \
  -H "Content-Type: application/json" \
  -d '{"wallet": "0xYourWallet", "amountUsdc": 2.0, "signature": "0x...", "nonce": "..."}'

# 5. Repay via x402 (returns 402 -- use with x402 client)
curl https://agentlending.spekn.com/loans/YOUR_LOAN_ID/pay

# 6. Or confirm repayment manually (requires on-chain tx hash, no signature)
curl -X POST https://agentlending.spekn.com/loans/YOUR_LOAN_ID/repay \
  -H "Content-Type: application/json" \
  -d '{"repaymentTx": "0x..."}'
```
