MIJI DApp Server Docs

Minting API Guide

모든 민팅 API는 x-api-key + X-CORPORATE-ID 헤더 인증이 필요합니다. X-CORPORATE-IDcorporateAccounts 컬렉션의 식별자이며, 동일한 기업 범위 내 데이터만 조회/수정할 수 있습니다.

공통 헤더

Name Required Value
x-api-key 글로벌 API 키
X-CORPORATE-ID corporateAccounts._id 또는 corporateId
Content-Type ⚠️ JSON Body가 있는 요청에서 application/json

POST /minting/order

민팅 주문을 생성하고 Bull minting-queue에 작업을 등록합니다. 주문이 생성되면 즉시 PENDING 상태로 응답하며, Processor가 실제 민팅을 수행해 CONFIRMED / FAILED 등으로 갱신합니다.

전제 조건

  1. Metadata 문서가 존재하고 chainId가 주문과 일치.
  2. DeployedContract 문서가 status: ACTIVE.

Headers

Name Required Value
x-api-key Yes 글로벌 API 키
X-CORPORATE-ID Yes corporateAccounts 식별자
Content-Type Yes application/json

Request Body

필드 타입 필수 설명
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 대납). 요청 시 지정하지 않으며, 결과 조회 시 확인용 필드입니다.

Sample

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"
  }'

서버는 contractAddressDeployedContract 문서를 조회해 ERC-721/1155 표준을 판별하고, 그에 따라 tokenIdamount를 검증합니다. ERC-721은 항상 1개만 민팅되며, ERC-1155는 지정한 tokenId 클래스를 amount 수량만큼 민팅합니다.

Sample (certificate, ERC-721) — 서버 메타데이터 API를 사용한 경우

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"
  }'

Sample (certificate, ERC-1155) — 서버 메타데이터 API를 사용한 경우

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 응답에 포함된 값을 그대로 사용하세요(직접 계산/입력 불필요).

응답 (201)

{
  "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분 이상 정체된 작업을 다시 큐에 넣습니다.


POST /minting/signature (Dev Only, 메타트랜잭션 민팅용 EIP-712 서명 생성)

개발 환경(TRANSFER_TEST_SIGNATURE=true)에서만 활성화됩니다.
사용자가 지갑에서 직접 서명할 수 있지만, 로컬 테스트를 빠르게 하기 위한 유틸입니다.

Request Body

필드 타입 필수 설명
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 키 사용

Sample (certificate, ERC-721)

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
  }'

Response

domain, types, request, signature, forwarderAddress를 반환합니다. request.gas/nonce는 문자열로 반환됩니다. 이 값을 그대로 /minting/relay에 전달하면 됩니다.


POST /minting/relay (메타트랜잭션 대납 민팅)

EIP-712 ForwardRequest에 서명한 payload를 전달하면, 서버가 forwarder.execute로 가스 대납 민팅을 수행합니다. certificate/standard 모두 지원하며, onlyOwner 제약은 그대로 적용됩니다(서명자가 오너여야 민팅 성공).

Request Body

필드 타입 필수 설명
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 가스 한도

빠른 테스트 흐름

  1. /minting/signature로 request+signature를 얻거나, 프런트/지갑에서 EIP-712 서명 생성.
  2. /minting/relay에 그대로 전달 → QUEUED 응답 → Processor가 forwarder.execute 실행.
  3. /minting/:id 또는 /minting/by-tx/:txHash 확인, mint.confirmed/failed 웹훅으로도 수신.

Sample (certificate, ERC-721)

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는 해당 필드를 무시.


GET /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 모듈이 추가되면 민팅 성공/실패 이벤트를 비동기로 받아 처리할 수 있습니다.


GET /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건이 반환됩니다.


GET /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"

POST /minting/occupancy/check

민팅 전에 토큰 ID/Metadata가 이미 사용 중인지 점검합니다. ERC-721은 토큰 ID가 고유해야 하므로, 해당 API 응답이 available: true일 때만 안전하게 민팅을 시도하는 것이 좋습니다. ERC-1155의 경우 notes 필드에 참고 정보가 포함됩니다.

Headers

Name Required Value
x-api-key Yes 글로벌 API 키
X-CORPORATE-ID Yes corporateAccounts 식별자
Content-Type Yes application/json

Request Body

필드 타입 필수 설명
chainId string 컨트랙트가 배포된 체인 ID
contractAddress string 점검 대상 컨트랙트 주소
tokenId string 확인할 토큰 ID
metadataId string(ObjectId) 특정 Metadata와의 충돌 여부까지 확인하려면 전달

Sample

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"
  }'

응답 (200)

{
  "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"
  }
}