모든 민팅 API는 x-api-key + X-CORPORATE-ID 헤더 인증이 필요합니다. X-CORPORATE-ID는 corporateAccounts 컬렉션의 식별자이며, 동일한 기업 범위 내 데이터만 조회/수정할 수 있습니다.
| Name | Required | Value |
|---|---|---|
x-api-key |
✅ | 글로벌 API 키 |
X-CORPORATE-ID |
✅ | corporateAccounts._id 또는 corporateId |
Content-Type |
⚠️ | JSON Body가 있는 요청에서 application/json |
/minting/order민팅 주문을 생성하고 Bull minting-queue에 작업을 등록합니다. 주문이 생성되면 즉시 PENDING 상태로 응답하며, Processor가 실제 민팅을 수행해 CONFIRMED / FAILED 등으로 갱신합니다.
Metadata 문서가 존재하고 chainId가 주문과 일치.DeployedContract 문서가 status: ACTIVE.| Name | Required | Value |
|---|---|---|
| x-api-key | Yes | 글로벌 API 키 |
| X-CORPORATE-ID | Yes | corporateAccounts 식별자 |
| Content-Type | Yes | application/json |
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
chainId |
string | ✅ | 민팅할 체인 ID |
contractAddress |
string | ✅ | 대상 컨트랙트 주소 (소문자 변환됨) |
receiverAddress |
string | ✅ | NFT 수신 지갑 주소 |
tokenId |
string | ✅ | 민팅할 토큰 ID (ERC-721/1155 공통) |
amount |
number | ⚠️ | ERC-721은 항상 1, ERC-1155는 1 이상 필수 |
metadataId |
string(ObjectId) | ✅ | 참조할 Metadata _id |
tokenUri |
string(url) | ⚠️ | certificate 타입 필수. 메타데이터 위치를 완성된 URI로 전달. 표준 컨트랙트는 무시. |
metadataHash |
string(0x+64 hex) | ⚠️ | certificate 타입 필수. 메타데이터 해시(SHA-256, canonical JSON). 표준 컨트랙트는 무시. |
mode |
string | 응답용 | direct(서버 서명) 또는 relay(Forwarder 대납). 요청 시 지정하지 않으며, 결과 조회 시 확인용 필드입니다. |
curl -X POST https://api.example.com/minting/order \
-H "x-api-key: ${GLOBAL_SECRET_KEY}" \
-H "X-CORPORATE-ID: ${CORPORATE_ID}" \
-H "Content-Type: application/json" \
-d '{
"chainId": "43114",
"contractAddress": "0xabc123...def",
"receiverAddress": "0xfeed1234...5678",
"tokenId": "1",
"metadataId": "6750121f7b3d9f1a6c4c4051"
}'
서버는
contractAddress로DeployedContract문서를 조회해 ERC-721/1155 표준을 판별하고, 그에 따라tokenId및amount를 검증합니다. ERC-721은 항상 1개만 민팅되며, ERC-1155는 지정한tokenId클래스를amount수량만큼 민팅합니다.
curl -X POST https://api.example.com/minting/order \
-H "x-api-key: ${GLOBAL_SECRET_KEY}" \
-H "X-CORPORATE-ID: ${CORPORATE_ID}" \
-H "Content-Type: application/json" \
-d '{
"chainId": "43114",
"contractAddress": "0xCERT721...",
"receiverAddress": "0xfeed1234...5678",
"tokenId": "1",
"metadataId": "6750121f7b3d9f1a6c4c4051",
"tokenUri": "https://cdn.example.com/meta/1.json",
"metadataHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}'
curl -X POST https://api.example.com/minting/order \
-H "x-api-key: ${GLOBAL_SECRET_KEY}" \
-H "X-CORPORATE-ID: ${CORPORATE_ID}" \
-H "Content-Type: application/json" \
-d '{
"chainId": "43114",
"contractAddress": "0xCERT1155...",
"receiverAddress": "0xfeed1234...5678",
"tokenId": "1001",
"amount": 1,
"metadataId": "6750121f7b3d9f1a6c4c4051",
"tokenUri": "https://cdn.example.com/meta/1001.json",
"metadataHash": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
}'
certificate 컨트랙트는 baseURI를 사용하지 않습니다. 민팅 시 전달한
tokenUri가 곧 온체인tokenURI/uri가 되며,metadataHash는 메타데이터 JSON을 canonical(키 정렬+공백 제거) 후 SHA-256으로 계산한 값이어야 합니다. 표준 컨트랙트(standard)는tokenUri/metadataHash를 무시합니다.
서버 메타데이터 API를 쓰지 않고 외부 메타데이터를 직접 쓸 경우, 동일 규칙으로 해시를 직접 계산해metadataHash에 넣으면 됩니다. 인증서(certificate) 민팅 시metadataHash는 메타데이터 생성 API 응답에 포함된 값을 그대로 사용하세요(직접 계산/입력 불필요).
{
"id": "6750132b7b3d9f1a6c4c4065",
"chainId": "43114",
"contractAddress": "0xabc123...def",
"receiverAddress": "0xfeed1234...5678",
"tokenId": "1",
"amount": 1,
"metadataId": "6750121f7b3d9f1a6c4c4051",
"status": "PENDING",
"createdAt": "2025-11-18T06:16:27.901Z",
"updatedAt": "2025-11-18T06:16:27.901Z"
}
상태 전이:
PENDING → (Processor) PROCESSING → 성공 시 CONFIRMED, 실패 시 FAILED (errorMessage 포함). 재시도 중이면 Bull 설정에 따라 자동 재삽입되며, Janitor가 5분 이상 정체된 작업을 다시 큐에 넣습니다.
/minting/signature (Dev Only, 메타트랜잭션 민팅용 EIP-712 서명 생성)개발 환경(
TRANSFER_TEST_SIGNATURE=true)에서만 활성화됩니다.
사용자가 지갑에서 직접 서명할 수 있지만, 로컬 테스트를 빠르게 하기 위한 유틸입니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
chainId |
string | ✅ | 예: 43113 |
contractAddress |
string | ✅ | 민팅할 컨트랙트 주소 |
receiverAddress |
string | ✅ | 수신자 주소 |
tokenId |
string | ✅ | 토큰 ID |
amount |
number | ⚠️ | ERC-1155만 사용 (기본 1) |
metadataId |
string(ObjectId) | ✅ | Metadata 문서 ID |
tokenUri |
string | ⚠️ | certificate 전용 필수 |
metadataHash |
string(0x+64) | ⚠️ | certificate 전용 필수 |
from |
string | ✅ | 서명자 주소(EOA) |
forwarderNonce |
string | ❌ | 미입력 시 on-chain 조회 |
forwarderAddress |
string | ❌ | corp 소유 Forwarder 지정 (없으면 자동 선택) |
gasLimit |
number | ❌ | forwarder.execute 가스 한도 |
privateKey |
string | ❌ | 테스트용. 주면 이 키로 서명, 없으면 서버 dev 키 사용 |
curl -X POST https://api.example.com/minting/signature \
-H "x-api-key: ${GLOBAL_SECRET_KEY}" \
-H "X-CORPORATE-ID: ${CORPORATE_ID}" \
-H "Content-Type: application/json" \
-d '{
"chainId": "43113",
"contractAddress": "0xCERT721...",
"receiverAddress": "0xReceiver...",
"tokenId": "1",
"metadataId": "6740f7a329d9f9323f8a9c91",
"tokenUri": "https://cdn.example.com/meta/1.json",
"metadataHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"from": "0xSigner...",
"forwarderAddress": "0xForwarder...",
"gasLimit": 800000
}'
domain, types, request, signature, forwarderAddress를 반환합니다. request.gas/nonce는 문자열로 반환됩니다. 이 값을 그대로 /minting/relay에 전달하면 됩니다.
/minting/relay (메타트랜잭션 대납 민팅)EIP-712 ForwardRequest에 서명한 payload를 전달하면, 서버가 forwarder.execute로 가스 대납 민팅을 수행합니다. certificate/standard 모두 지원하며, onlyOwner 제약은 그대로 적용됩니다(서명자가 오너여야 민팅 성공).
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
chainId |
string | ✅ | 체인 ID |
contractAddress |
string | ✅ | 컨트랙트 주소 |
receiverAddress |
string | ✅ | 수신자 주소 |
tokenId |
string | ✅ | 토큰 ID |
amount |
number | ⚠️ | ERC-1155만 사용 (기본 1) |
metadataId |
string(ObjectId) | ✅ | Metadata ID |
tokenUri |
string | ⚠️ | certificate 필수 |
metadataHash |
string(0x+64) | ⚠️ | certificate 필수 |
from |
string | ✅ | 서명자 주소(EOA) |
signature |
string | ✅ | EIP-712 ForwardRequest 서명 |
forwarderNonce |
string | ❌ | 미입력 시 on-chain 조회 |
forwarderAddress |
string | ❌ | corp 소유 Forwarder 지정 (없으면 자동 선택) |
gasLimit |
number | ❌ | forwarder.execute 가스 한도 |
/minting/signature로 request+signature를 얻거나, 프런트/지갑에서 EIP-712 서명 생성./minting/relay에 그대로 전달 → QUEUED 응답 → Processor가 forwarder.execute 실행./minting/:id 또는 /minting/by-tx/:txHash 확인, mint.confirmed/failed 웹훅으로도 수신.curl -X POST https://api.example.com/minting/relay \
-H "x-api-key: ${GLOBAL_SECRET_KEY}" \
-H "X-CORPORATE-ID: ${CORPORATE_ID}" \
-H "Content-Type: application/json" \
-d '{
"chainId": "43113",
"contractAddress": "0xCERT721...",
"receiverAddress": "0xReceiver...",
"tokenId": "1",
"metadataId": "6740f7a329d9f9323f8a9c91",
"tokenUri": "https://cdn.example.com/meta/1.json",
"metadataHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"from": "0xSigner...",
"signature": "0xSignatureFromEIP712",
"forwarderAddress": "0xForwarder...",
"gasLimit": 800000
}'
주의: onlyOwner 민팅이므로 서명자(
from)가 오너여야 성공. certificate는tokenUri/metadataHash필수, standard는 해당 필드를 무시.
/minting/:id주문 상태를 조회합니다.
curl -X GET https://api.example.com/minting/6750132b7b3d9f1a6c4c4065 \
-H "x-api-key: ${GLOBAL_SECRET_KEY}" \
-H "X-CORPORATE-ID: ${CORPORATE_ID}"
MintingOrderResponseDto 구조:
| 필드 | 설명 |
|---|---|
status |
PENDING, PROCESSING, SENT, CONFIRMED, FAILED 중 하나 |
txHash |
민팅 거래 해시 (CONFIRMED 시 채워짐) |
mintingGasUsed |
소비된 가스 (wei) |
completedAt |
CONFIRMED/FAILED 시각 |
errorMessage |
실패 원인 |
totalFeeAvax |
가스 사용량 × 실효 가스비를 AVAX 단위로 환산한 문자열 |
avaxPriceUsd, avaxPriceKrw |
민팅 확정 시점 CoinGecko 환율(USD/KRW) |
totalFeeUsd, totalFeeKrw |
AVAX 사용량에 환율을 곱한 최종 정산 금액 |
해당 응답을 Polling하거나, 추후 Webhook 모듈이 추가되면 민팅 성공/실패 이벤트를 비동기로 받아 처리할 수 있습니다.
/minting/by-tx/:txHash민팅 트랜잭션 해시로 주문을 조회합니다. 민팅이 완료되어 txHash가 기록된 주문만 조회됩니다.
curl -X GET https://api.example.com/minting/by-tx/0xabc... \
-H "x-api-key: ${GLOBAL_SECRET_KEY}" \
-H "X-CORPORATE-ID: ${CORPORATE_ID}"
성공 시 MintingOrderResponseDto 1건이 반환됩니다.
/minting/by-token특정 NFT(컨트랙트 주소 + tokenId)의 모든 민팅 주문을 조회합니다.
curl -G https://api.example.com/minting/by-token \
-H "x-api-key: ${GLOBAL_SECRET_KEY}" \
-H "X-CORPORATE-ID: ${CORPORATE_ID}" \
--data-urlencode "contractAddress=0xabc123...def" \
--data-urlencode "tokenId=1"
/minting/occupancy/check민팅 전에 토큰 ID/Metadata가 이미 사용 중인지 점검합니다. ERC-721은 토큰 ID가 고유해야 하므로, 해당 API 응답이 available: true일 때만 안전하게 민팅을 시도하는 것이 좋습니다. ERC-1155의 경우 notes 필드에 참고 정보가 포함됩니다.
| Name | Required | Value |
|---|---|---|
| x-api-key | Yes | 글로벌 API 키 |
| X-CORPORATE-ID | Yes | corporateAccounts 식별자 |
| Content-Type | Yes | application/json |
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
chainId |
string | ✅ | 컨트랙트가 배포된 체인 ID |
contractAddress |
string | ✅ | 점검 대상 컨트랙트 주소 |
tokenId |
string | ✅ | 확인할 토큰 ID |
metadataId |
string(ObjectId) | ❌ | 특정 Metadata와의 충돌 여부까지 확인하려면 전달 |
curl -X POST https://api.example.com/minting/occupancy/check \
-H "x-api-key: ${GLOBAL_SECRET_KEY}" \
-H "X-CORPORATE-ID: ${CORPORATE_ID}" \
-H "Content-Type: application/json" \
-d '{
"chainId": "43114",
"contractAddress": "0xabc123...def",
"tokenId": "1",
"metadataId": "6750121f7b3d9f1a6c4c4051"
}'
{
"available": false,
"ercStandard": "721",
"reasons": [
"Metadata already linked to a different contract.",
"Token already linked to metadata 6750121f7b3d9f1a6c4c4051."
],
"notes": [],
"activeOrderCount": 2,
"metadataContext": {
"metadataId": "6750121f7b3d9f1a6c4c4051",
"linkedContractAddress": "0xabc123...def",
"linkedTokenId": "1"
}
}
available: true면 현재 요청 값으로 민팅이 가능함을 의미.reasons: 사용이 불가능한 경우의 상세 사유.notes: ERC-1155처럼 사용 가능하지만 참고가 필요한 경우 안내 메시지.activeOrderCount: 해당 토큰 ID와 관련된 민팅 주문 수 (과거 포함).metadataContext: Metadata가 이미 링크된 컨트랙트/토큰 정보.