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

# AFK API v1

> AFK Crypto API v1 개요 및 규약

## 개요

* 기본 경로: `/api/v1`
* 인증: `x-api-key` 헤더의 API 키
* 멱등성: 쓰기 작업은 `Idempotency-Key` 헤더(UUID) 필요
* 응답 형식: 모든 응답에는 추적을 위한 `x-request-id` 헤더 포함

### 엔드포인트

* `GET /api/v1/wallets` – 사용자 지갑 목록
* `GET /api/v1/wallets/balances` – 호출자 지갑 잔액(체인별; 기본 지갑 사용)
* `GET /api/v1/wallets/:address/balances` – 소유 지갑 주소 잔액
* `GET /api/v1/tx/:id` – 트랜잭션 상세 조회
* `POST /api/v1/send` – 네이티브/토큰 전송 (EVM + Solana)
* `POST /api/v1/token/approve` – ERC20 토큰 승인 (EVM 전용)
* `POST /api/v1/contracts/send` – 일반 컨트랙트 호출 (EVM 전용)
* `POST /api/v1/trade/quote` – 스왑 견적 (EVM + Solana)
* `POST /api/v1/trade/swap` – 스왑 실행 (EVM + Solana)

## 체인

지원 체인 전체 목록은 [지원 체인](/api-reference/supported-chains/)에서 확인하세요. 요청의 `chain` 필드에는 슬러그(예: `base`, `solana-devnet`)를 사용합니다.

## 요청 제한

* **쓰기**(`POST /api/v1/trade/quote` 포함): 사용자당 분당 15 요청
* **읽기**: 사용자당 분당 60 요청
* 응답: 초과 시 HTTP 429 반환
* 헤더: `Retry-After`(다음 윈도우까지의 초)

## 멱등성(쓰기)

* 모든 변경 엔드포인트는 `Idempotency-Key`가 필요합니다.
* 동일한 본문으로 키를 재사용하면 원래 200 응답을 반환합니다.
* 다른 본문으로 재사용하면 HTTP 409와 `code: IDEMPOTENT_BODY_MISMATCH`를 반환합니다.
* 저장된 성공 응답 없이 재사용하면 HTTP 409와 `code: IDEMPOTENT_REPLAY`를 반환합니다.
* 키는 인증된 사용자 범위이며, 엔드포인트 경로가 추적으로 기록됩니다.
* 적용 대상: `POST /api/v1/send`, `POST /api/v1/token/approve`, `POST /api/v1/contracts/send`, `POST /api/v1/trade/swap`.

## 오류 처리

### 오류 응답 형식

```json theme={null}
{
  "error": "Human-readable error message",
  "code": "ERROR_CODE",
  "requestId": "unique-request-id"
}
```

### 오류 코드

* `UNAUTHORIZED` – 인증 누락/무효 또는 API 키 오류 (HTTP 401)
* `FORBIDDEN` – 인증되었으나 작업 권한 없음 (HTTP 403)
* `NOT_FOUND` – 리소스를 찾을 수 없음 (HTTP 404)
* `RATE_LIMITED` – 요청 제한 초과 (HTTP 429)
* `INVALID_INPUT` – 잘못된 요청 파라미터 (HTTP 400)
* `WALLET_NOT_FOUND` – 지정된 지갑을 찾을 수 없음
* `USER_NOT_LINKED` – 사용자가 Privy에 연결되지 않음
* `WALLET_NOT_DELEGATED` – 지갑이 서버 서명자에게 위임되지 않음
* `WALLET_ID_REQUIRED` – Privy 지갑 ID 누락
* `CHAIN_UNKNOWN` – 알 수 없거나 지원되지 않는 체인
* `INSUFFICIENT_FUNDS` – 송신자의 자금 부족(가치/수수료)
* `IDEMPOTENT_BODY_MISMATCH` – 동일한 멱등 키로 다른 요청 본문 (HTTP 409)
* `IDEMPOTENT_REPLAY` – 멱등 키가 이미 사용됨 (HTTP 409)
* `PRIVY_RPC_ERROR` – Privy RPC 서비스 오류
* `SEND_FAILED` – 트랜잭션 제출 실패
* `SERVICE_UNAVAILABLE` – 필요한 서비스가 구성되지 않음
* `QUOTE_FAILED` – 견적 서비스 오류 (HTTP 400)
* `INTERNAL_ERROR` – 서버 오류

<Note>
  **QUOTE\_FAILED 세부사항:**

  * **Solana/Jupiter**: 일부 Solana mint는 Jupiter에서 거래할 수 없습니다(선별된 허용 목록). 이 경우 API는 HTTP 400과 `code: QUOTE_FAILED`, "Token not tradable on Jupiter"와 같은 오류 메시지를 반환합니다.
  * **EVM/1inch**: 토큰이 1inch에서 지원되지 않는 경우 API는 HTTP 400과 `code: QUOTE_FAILED`, "Token not tradable on 1inch"와 같은 메시지를 반환합니다.
  * 요청된 출력 토큰/mint가 업스트림 제공자에 의해 거래 불가로 표시된 경우 이는 예상된 동작이며, 다른 곳에 풀이 존재하더라도 발생합니다.
</Note>

## 검증

### 주소 형식

* EVM: `/^0x[a-fA-F0-9]{40}$/` 정규식과 일치해야 합니다
* Solana: 유효한 base58 공개키여야 합니다

### 공통 매개변수

* **금액(EVM)**: 정수 문자열만 허용(10진수 또는 0x-hex). 음수가 될 수 없습니다. ERC20 및 `value`의 경우 uint256에 맞아야 합니다.
* **금액(Solana)**: 기본 단위의 정수 문자열. SPL 금액은 부호 없는 64비트 범위 이내여야 합니다.
* **송신자(`from`)**: 선택 사항. 생략 시 지정한 체인에 대해 사용자의 기본 지갑이 사용됩니다.
* **멱등성**: 모든 쓰기 엔드포인트는 `Idempotency-Key` 헤더가 필요합니다. 동일한 본문으로 반복하면 원래 응답을 반환합니다.

### 네이티브 토큰 키워드

거래 엔드포인트(`/api/v1/trade/quote`, `/api/v1/trade/swap`)는 `fromToken`/`toToken`에 대소문자를 구분하지 않는 `NATIVE` 키워드를 허용합니다:

* **EVM**: `NATIVE`는 `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`로 해석됩니다
* **Solana**: `NATIVE`는 래핑된 SOL mint `So11111111111111111111111111111111111111112`로 해석됩니다
* 응답은 해석된 주소를 반환합니다(`NATIVE` 아님)
* 전송 엔드포인트는 네이티브 전송에 토큰 주소 대신 `asset: "native"`를 사용합니다

## 규약

* 체인 선택: `chain` 슬러그를 사용합니다(예: `base`, `base-sepolia`, `solana-devnet`).
* Solana `Transaction.chainId` 센티널 매핑: `0` = mainnet, `-2` = testnet, `-3` = devnet.
* 멱등성: 사용자/키별로 고유합니다. 재전송은 원래 응답을 반환하며, 본문이 다르면 409를 반환합니다.

## 관련

<CardGroup cols={2}>
  <Card title="지원 체인" icon="link-simple" href="/api-reference/supported-chains/" />

  <Card title="정책 및 보안" icon="shield" href="/api-reference/policies-security/" />
</CardGroup>
