Internal Endpoints
These endpoints are called by the CRE workflows and are authenticated via the x-api-key header. They are not intended for direct user access.
All internal endpoints are mounted under /api/v1/internal/.
GET /internal/pending-intents
Fetch all active lend intents and pending borrow intents for the current matching epoch.
Response
{
"lendIntents": [
{
"intentId": "intent_001",
"userId": "0xAlice...",
"token": "0xgUSD...",
"amount": "10000000000",
"encryptedRate": "04a1b2c3...",
"epochId": "epoch_42"
}
],
"borrowIntents": [
{
"intentId": "borrow_001",
"borrower": "0xBob...",
"token": "0xgUSD...",
"amount": "8000000000",
"encryptedMaxRate": "04d5e6f7...",
"collateralToken": "0xgETH...",
"collateralAmount": "5000000000",
"status": "pending"
}
]
}
Behavior
Returns lend intents that are not currently locked in pending proposals. This prevents double matching of the same liquidity across epochs.
POST /internal/record-match-proposals
Submit match proposals generated by the CRE matching engine.
Request Body
{
"proposals": [
{
"borrowIntentId": "borrow_001",
"borrower": "0xBob...",
"token": "0xgUSD...",
"principal": "8000000000",
"matchedTicks": [
{ "lender": "0xAlice...", "lendIntentId": "intent_001", "amount": "5000000000", "rate": 0.035 },
{ "lender": "0xCarol...", "lendIntentId": "intent_002", "amount": "3000000000", "rate": 0.04 }
],
"effectiveBorrowerRate": 0.0369,
"collateralToken": "0xgETH...",
"collateralAmount": "5000000000"
}
]
}
Behavior
- Creates
MatchProposalrecords with statuspending - Sets expiration time (5 seconds in current implementation)
- Updates associated borrow intents to status
proposed - Locks the lend intents referenced in matched ticks
POST /internal/expire-proposals
Auto accept proposals that have passed their expiration window.
Behavior
- Finds all proposals where
expiresAt < nowandstatus === "pending" - For each expired proposal, performs the same logic as
acceptProposal: a. Creates an active loan b. Consumes matched lend ticks c. Queues principal disbursement transfer - Marks the proposal as
accepted
This ensures proposals are never left in limbo. The CRE calls this endpoint at the beginning of each matching epoch before fetching new intents.
GET /internal/check-loans
Return all active loans for the CRE to perform health checks.
Response
{
"loans": [
{
"loanId": "loan_001",
"borrower": "0xBob...",
"token": "0xgUSD...",
"principal": "8000000000",
"collateralToken": "0xgETH...",
"collateralAmount": "5000000000",
"requiredCollateral": "4500000000",
"maturity": "2026-04-09T00:00:00Z",
"matchedTicks": [...]
}
]
}
GET /internal/pending-transfers
Fetch transfers queued by the server that need to be executed via the vault.
Response
{
"transfers": [
{
"id": "tx_001",
"recipient": "0xAlice...",
"token": "0xgUSD...",
"amount": "5000000000",
"reason": "disburse",
"createdAt": "2026-03-09T12:00:00Z",
"status": "pending"
}
]
}
POST /internal/confirm-transfers
Mark transfers as completed after the CRE has executed them through the vault.
Request Body
{
"transferIds": ["tx_001", "tx_002"]
}
Behavior
Updates the status of each transfer from pending to completed. This prevents the CRE from re executing the same transfer on subsequent polling cycles.
POST /internal/liquidate-loans
Trigger liquidation for undercollateralized or expired loans.
Request Body
{
"loanIds": ["loan_001", "loan_003"]
}
Behavior
For each loan ID:
- Marks the loan as
defaulted - Downgrades the borrower's credit tier by one level
- Calculates the 5% protocol fee from collateral
- Distributes 95% of collateral pro rata to lenders based on tick amounts
- Queues transfer of protocol fee (reason:
liquidate) - Queues individual transfers to each lender (reason:
liquidate)
Response
{
"liquidated": 2,
"transfersQueued": 5
}
Authentication
All internal endpoints require the x-api-key header:
x-api-key: <value of INTERNAL_API_KEY env var>
Requests without a valid key receive a 401 Unauthorized response.