CL2C raw specification
The OpenAPI 3.0.3 document backing the CL2C API reference, viewable as YAML or JSON.
openapi: 3.0.3
info:
title: Taliware CL2C API
version: 1.0.0
description: |
The CL2C API is the primary developer-facing surface for managing organizations,
end-users, smart contracts, and NFTs on the Taliware platform.
## Authentication
All endpoints require an API key. Pass it in one of two ways:
- **Header**: `x-api-key: <your-api-key>`
- **Bearer token**: `Authorization: Bearer <your-api-key>`
Retrieve your API key from the Developer Platform → your organization's settings page.
## Base URL
`https://developer.taliware.com/api/v1`
## API overview
| Resource | Path | Description |
|---|---|---|
| Contract | `/cl2c/contract` | Create, deploy, and manage ERC-1155 smart contracts |
| User | `/cl2c/user` | Invite and manage end-users in your organization |
| NFT | `/cl2c/nft` | Mint digital assets, track ownership and confirmation status |
| Token | `/cl2c/token` | Check CRDB balances and transfer tokens to members |
> **Partner integrations** that need app-owned biometric proof or Confida QR login
> should also review the **Cordoba API** (`/api/v1/cordoba`). CL2C and Cordoba share
> the same authentication (API key) and data model.
## NFT lifecycle
```
Create Contract ──► Deploy Contract ──► Invite Users ──► Mint NFT
│ (on-chain) │ │
│ │ PENDING owners
│ │ receive email
└────────────────────────────────────────────┘
Users confirm in Confida
│
All confirmed?
│
┌─── YES ───┴─── NO ───┐
│ │
MINTED WAITING...
(on-chain)
```
**Step-by-step:**
1. `POST /cl2c/contract` — create a contract record (status: `CREATED`)
2. `PUT /cl2c/contract/{id}` — deploy on-chain (status: `DEPLOYED`)
3. `POST /cl2c/user` — invite end-users (or use bulk at `/cl2c/user/bulk`)
4. `POST /cl2c/nft` — mint an NFT; one `copyright` entry is created per owner (status: `CREATED`); confirmation emails are sent
5. End-users open the **Confida app** and approve → once all copyright holders confirm, minting is triggered automatically (status: `MINTED`)
6. On-chain data (txHash, IPFS CIDs, gas fee) is written to `metadata` and readable at `GET /cl2c/nft/{id}`
## CRDB Token types
- **Mainnet CRDB** — real tokens on Polygon Mainnet, required for live minting
- **Testnet CRDB** — free faucet tokens on Polygon Amoy, for development and testing only
Purchase tokens from the Developer Platform settings page (Stripe card or MetaMask MATIC).
servers:
- url: https://developer.taliware.com/api/v1
description: Production
tags:
- name: Contract
description: Create, deploy, and manage ERC-1155 smart contracts
- name: User
description: Invite and manage end-users in your organization
- name: NFT
description: Mint digital assets, and track ownership and confirmation status
- name: Tokens
description: Check CRDB balances and transfer tokens to members
components:
securitySchemes:
apiKeyAuth:
type: apiKey
in: header
name: x-api-key
apiKeyBearerAuth:
type: http
scheme: bearer
bearerFormat: API key
cookieAuth:
type: apiKey
in: cookie
name: next-auth.session-token
schemas:
# Generic error shape used across endpoints
Error:
type: object
description: Standard error payload
properties:
error:
type: string
details:
type: array
items:
type: string
# Simple pagination envelope used by list endpoints
Pagination:
type: object
properties:
page:
type: integer
description: Current page (1-indexed)
limit:
type: integer
description: Items per page
total:
type: integer
description: Total number of matching records
totalPages:
type: integer
hasNext:
type: boolean
hasPrev:
type: boolean
PaginatedResponse:
type: object
properties:
data:
type: array
items:
type: object
pagination:
$ref: '#/components/schemas/Pagination'
filters:
type: object
additionalProperties: true
# Contract
Contract:
type: object
properties:
id:
type: string
name:
type: string
symbol:
type: string
description:
type: string
network:
type: string
env:
type: string
status:
type: string
enum: [CREATED, DEPLOYED, FAILED]
contractAddress:
type: string
deployedAt:
type: string
format: date-time
metadata:
type: object
totalNFTs:
type: integer
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
ContractCreate:
type: object
required: [name, symbol]
properties:
name:
type: string
symbol:
type: string
description:
type: string
network:
type: string
enum: [POLYGON]
env:
type: string
enum: [TESTNET, MAINNET]
metadata:
type: object
ContractUpdate:
type: object
required: [id]
properties:
id:
type: string
status:
type: string
enum: [CREATED, DEPLOYED, FAILED]
contractAddress:
type: string
deployedAt:
type: string
format: date-time
ContractDelete:
type: object
required: [contractId]
properties:
contractId:
type: string
# User
CreateUser:
type: object
required:
- email
properties:
email:
type: string
format: email
phone:
type: string
nullable: true
BulkUserEntry:
type: object
required:
- email
properties:
email:
type: string
format: email
phone:
type: string
nullable: true
BulkCreateUser:
type: object
required:
- users
properties:
users:
type: array
minItems: 1
maxItems: 100
items:
$ref: '#/components/schemas/BulkUserEntry'
BulkUserResult:
type: object
properties:
email:
type: string
format: email
status:
type: string
enum: [invited, skipped, failed]
reason:
type: string
nullable: true
description: Present when status is skipped or failed.
id:
type: string
nullable: true
description: Invitation ID, present when status is invited.
BulkCreateUserResponse:
type: object
properties:
data:
type: object
properties:
results:
type: array
items:
$ref: '#/components/schemas/BulkUserResult'
summary:
type: object
properties:
total:
type: integer
description: Number of unique emails processed.
invited:
type: integer
skipped:
type: integer
description: Already a member or pending invitation.
failed:
type: integer
description: Unexpected errors during invitation creation.
UserOrgSummary:
type: object
properties:
id:
type: string
email:
type: string
walletAddress:
type: string
nullable: true
totalNFTs:
type: integer
status:
type: string
enum: [ACTIVE, INVITED]
createdAt:
type: string
format: date-time
nullable: true
updatedAt:
type: string
format: date-time
nullable: true
user:
$ref: '#/components/schemas/UserInfo'
UserOrgItem:
type: object
properties:
data:
$ref: '#/components/schemas/UserOrgSummary'
UserInfo:
type: object
properties:
id:
type: string
nullable: true
name:
type: string
nullable: true
image:
type: string
nullable: true
emailVerified:
type: boolean
nullable: true
isRegistered:
type: boolean
UpdateUser:
type: object
properties:
email:
type: string
format: email
resend:
type: boolean
description: Resend invitation (only for pending invitations)
UserOrgDetail:
type: object
properties:
id:
type: string
email:
type: string
walletAddress:
type: string
nullable: true
user:
type: object
properties:
name:
type: string
nullable: true
image:
type: string
nullable: true
endUserNfts:
type: array
items:
type: object
properties:
status:
type: string
percentage:
type: number
copyAuthLocation:
type: string
nullable: true
copyAuthTimestamp:
type: string
format: date-time
nullable: true
nft:
type: object
properties:
id:
type: string
status:
type: string
mintedAt:
type: string
format: date-time
supply:
type: integer
name:
type: string
description:
type: string
nullable: true
externalUrl:
type: string
nullable: true
imagePath:
type: string
nullable: true
smartContract:
type: object
properties:
name:
type: string
symbol:
type: string
contractAddress:
type: string
status:
type: string
enum: [ACTIVE, INVITED]
UserOrgUpdateResponse:
type: object
properties:
id:
type: string
email:
type: string
format: email
walletAddress:
type: string
nullable: true
# NFT
MintRequest:
type: object
required: [name, smartContractId, copyright]
properties:
name:
type: string
description:
type: string
externalUrl:
type: string
imagePath:
type: string
description: >
Optional. ipfs:// URI, data URI, raw base64, http(s) URL, or local path for
the asset's image. If omitted, the NFT is created as traceability-only —
an on-chain record and metadata JSON are created with no IPFS file upload.
metadata:
type: object
smartContractId:
type: string
supply:
type: integer
copyright:
type: array
items:
type: object
required: [userId, percentage]
properties:
userId:
type: string
percentage:
type: number
UpdateNFT:
type: object
properties:
id:
type: string
name:
type: string
description:
type: string
status:
type: string
# enum: [PENDING, CREATED, MINTED, ATTACHED, FAILED]
enum: [PENDING, CREATED, MINTED, FAILED]
mintedAt:
type: string
format: date-time
DeleteNFTRequest:
type: object
properties:
nftId:
type: string
NFTSummary:
type: object
properties:
id:
type: string
status:
type: string
name:
type: string
description:
type: string
externalUrl:
type: string
imagePath:
type: string
supply:
type: integer
mintedAt:
type: string
format: date-time
smartContract:
type: object
properties:
id:
type: string
name:
type: string
symbol:
type: string
contractAddress:
type: string
status:
type: string
network:
type: string
env:
type: string
NFTDetail:
allOf:
- $ref: '#/components/schemas/NFTSummary'
- type: object
properties:
metadata:
type: object
description: |
On-chain metadata recorded after minting. Common fields:
- `transactionHash` — blockchain tx hash (0x…, 66 chars)
- `gasFee` — gas paid in wei (string, convert with /1e18 to get ETH)
- `confirmationTime` — ISO 8601 timestamp when tx was confirmed
- `ipfsMetadata` — IPFS CID of the metadata JSON (Qm…)
- `ipfsCopyright` — IPFS CID of the copyright JSON
additionalProperties: true
copyright:
type: array
description: Per-owner copyright and confirmation records.
items:
type: object
properties:
id:
type: string
status:
type: string
enum: [PENDING, CONFIRMED, REJECTED, MINTED]
description: Confirmation status for this copyright holder.
percentage:
type: number
description: Ownership percentage (0–100). All owners must sum to 100.
email:
type: string
copyAuthLocation:
type: string
nullable: true
description: Geolocation or description recorded at time of biometric confirmation.
copyAuthTimestamp:
type: string
format: date-time
nullable: true
description: When the owner confirmed (or rejected) the copyright.
walletAddress:
type: array
nullable: true
items:
type: object
properties:
address:
type: string
isPrimary:
type: boolean
userName:
type: string
nullable: true
userImage:
type: string
nullable: true
totalOwners:
type: integer
UpdateNFTbyID:
type: object
properties:
name:
type: string
description:
type: string
externalUrl:
type: string
format: uri
supply:
type: integer
minimum: 1
metadata:
type: object
additionalProperties: true
TokenBalanceResponse:
type: object
properties:
balance:
type: number
walletAddress:
type: string
nullable: true
TokenBalancesResponse:
type: object
properties:
mainnet:
$ref: '#/components/schemas/TokenBalanceResponse'
faucet:
allOf:
- $ref: '#/components/schemas/TokenBalanceResponse'
nullable: true
TokenSendRequest:
type: object
required: [memberId, amount]
properties:
memberId:
type: string
amount:
type: number
minimum: 0
exclusiveMinimum: true
tokenType:
type: string
enum: [mainnet, faucet]
default: mainnet
TokenSendResponse:
type: object
properties:
success:
type: boolean
example: true
transactionHash:
type: string
nullable: true
tokenType:
type: string
enum: [mainnet, faucet]
StripeCheckoutRequest:
type: object
required: [amount]
properties:
amount:
type: number
minimum: 1
StripeCheckoutResponse:
type: object
properties:
sessionId:
type: string
checkoutUrl:
type: string
paths:
# Contracts
/cl2c/contract:
get:
tags:
- Contract
summary: List smart contracts for the authenticated organization
description: Retrieve smart contract records belonging to the organization identified by the X-API-KEY header.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
parameters:
- in: query
name: page
schema:
type: integer
- in: query
name: limit
schema:
type: integer
- in: query
name: search
schema:
type: string
- in: query
name: status
schema:
type: string
enum: [CREATED, DEPLOYED, FAILED]
- in: query
name: sortBy
schema:
type: string
- in: query
name: sortOrder
schema:
type: string
enum: [asc, desc]
responses:
'200':
description: Array of contracts with pagination info
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Contract'
pagination:
$ref: '#/components/schemas/Pagination'
filters:
type: object
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Contract
summary: Create a new smart contract record (not deployed yet)
description: Create a smart contract entry in the system (deployment is a separate action).
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ContractCreate'
responses:
'201':
description: Contract created
content:
application/json:
schema:
$ref: '#/components/schemas/Contract'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Contract already exists
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
tags:
- Contract
summary: Update a smart contract
description: Update status, contractAddress, or deployedAt of an existing contract.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ContractUpdate'
responses:
'200':
description: Contract updated
content:
application/json:
schema:
$ref: '#/components/schemas/Contract'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Contract not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Contract
summary: Delete a smart contract
description: Delete a contract if it is not deployed and has no associated NFTs.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ContractDelete'
responses:
'200':
description: Contract deleted successfully
content:
application/json:
schema:
type: object
properties:
message:
type: string
deletedContract:
type: object
properties:
id:
type: string
name:
type: string
'400':
description: Bad request / cannot delete
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Contract not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
# Contracts by ID
/cl2c/contract/{id}:
put:
tags:
- Contract
summary: Deploy smart contract (trigger on-chain deploy)
description: Triggers on-chain contract deployment for the specified contract record. Only works if the contract is not already deployed.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
description: The ID of the contract to deploy
responses:
'200':
description: Contract deployed successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Contract'
'400':
description: Bad request (e.g., invalid ID or contract already deployed)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Contract not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Contract
summary: Delete a smart contract record
description: Remove a smart contract record from the system. Only allowed if no associated NFTs exist and the contract is not deployed.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
description: The ID of the contract to delete
responses:
'200':
description: Contract deleted successfully
content:
application/json:
schema:
type: object
properties:
message:
type: string
deletedContract:
type: object
properties:
id:
type: string
name:
type: string
'400':
description: Bad request (contract deployed or has associated NFTs)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Contract not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
# Users (organization-scoped)
/cl2c/user:
get:
tags:
- User
summary: List users (userOrganization records) in the authenticated organization
description: Returns a paginated list of userOrganization entries (members + pending invitations) for the organization tied to the X-API-KEY.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
parameters:
- in: query
name: page
schema:
type: integer
- in: query
name: limit
schema:
type: integer
- in: query
name: search
schema:
type: string
- in: query
name: status
schema:
type: string
- in: query
name: sortBy
schema:
type: string
- in: query
name: sortOrder
schema:
type: string
enum: [asc, desc]
- in: query
name: hasWallet
schema:
type: boolean
responses:
'200':
description: Paginated list of userOrganization records
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/UserOrgSummary'
pagination:
$ref: '#/components/schemas/Pagination'
filters:
type: object
additionalProperties: true
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- User
summary: Invite (create) a userOrganization record for this organization
description: Create an invited (or existing) userOrganization for the organization. If the email matches a registered user, userId will be linked automatically.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUser'
responses:
'201':
description: Created userOrganization
content:
application/json:
schema:
$ref: '#/components/schemas/UserOrgItem'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict (already exists)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
# Bulk user invite
/cl2c/user/bulk:
post:
tags:
- User
summary: Bulk invite users to the organization
description: |
Invite up to 100 users in a single request. Each entry is processed independently.
Returns HTTP 207 (Multi-Status) with per-user results. Duplicate emails within the
request are deduplicated automatically. Emails already a member or with a pending
invitation are reported as `skipped`, not `failed`.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/BulkCreateUser'
example:
users:
- email: alice@example.com
- email: bob@example.com
phone: "+1 555 000 0001"
responses:
'207':
description: Multi-status — individual results per email address
content:
application/json:
schema:
$ref: '#/components/schemas/BulkCreateUserResponse'
'400':
description: Bad request (invalid body, exceeds 100-user limit, etc.)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Organization not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
# User by ID
/cl2c/user/{id}:
get:
tags:
- User
summary: Get a specific userOrganization by id (admin/org-scoped)
description: Retrieve a userOrganization entry plus linked user and NFT ownership info. Includes pending invitations if user not yet registered.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
description: The ID of the userOrganization or invitation
responses:
'200':
description: userOrganization detail
content:
application/json:
schema:
$ref: '#/components/schemas/UserOrgDetail'
'400':
description: Bad request (invalid ID)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found (user or invitation does not exist)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
tags:
- User
summary: Update a user or invitation email
description: Update email for a member or invitation. Resend is only allowed for invitations.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
description: The ID of the userOrganization or invitation
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateUser'
responses:
'200':
description: Updated userOrganization or invitation
content:
application/json:
schema:
$ref: '#/components/schemas/UserOrgUpdateResponse'
'400':
description: Bad request (invalid body, resend for member, etc.)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict (duplicate email or wallet)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- User
summary: Delete a userOrganization by id (admin)
description: Delete a userOrganization or pending invitation. Users with wallet addresses or NFTs cannot be deleted.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
description: The ID of the userOrganization or invitation
responses:
'200':
description: Deleted successfully
content:
application/json:
schema:
type: object
properties:
message:
type: string
'400':
description: Bad request (user has wallet or NFTs)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
# NFT collection
/cl2c/nft:
get:
tags:
- NFT
summary: List NFTs for the authenticated organization
description: Returns NFTs for the organization's smart contracts. Supports search, status, contractId filters, and pagination.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
parameters:
- in: query
name: page
schema:
type: integer
- in: query
name: limit
schema:
type: integer
- in: query
name: search
schema:
type: string
description: Search NFTs by name or description
- in: query
name: status
schema:
type: string
description: Filter by NFT status (CREATED, PENDING, MINTED, FAILED)
- in: query
name: contractId
schema:
type: string
description: Filter NFTs by a specific smart contract ID
- in: query
name: sortBy
schema:
type: string
- in: query
name: sortOrder
schema:
type: string
enum: [asc, desc]
responses:
'200':
description: Paginated list of NFTs
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/NFTSummary'
pagination:
$ref: '#/components/schemas/Pagination'
filters:
type: object
additionalProperties: true
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- NFT
summary: Create (mint) a new NFT
description: Creates NFT row with status=CREATED and pending userNft entries for owners; may upload image to IPFS and send notifications.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/MintRequest'
responses:
'201':
description: NFT created (userNft entries created and notifications sent)
content:
application/json:
schema:
$ref: '#/components/schemas/NFTDetail'
'400':
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Related resource not found (e.g., smart contract or user)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
tags:
- NFT
summary: Update NFT metadata or status
description: Update name, description, status, or mintedAt for an NFT.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateNFT'
responses:
'200':
description: NFT updated
content:
application/json:
schema:
$ref: '#/components/schemas/NFTSummary'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: NFT not found in organization
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- NFT
summary: Delete an NFT
description: Delete an NFT and all its pending userNft entries. Minted NFTs cannot be deleted.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DeleteNFTRequest'
responses:
'200':
description: NFT deleted successfully
content:
application/json:
schema:
type: object
properties:
message:
type: string
deletedNft:
type: object
properties:
id:
type: string
name:
type: string
'400':
description: Bad request (e.g., cannot delete minted NFT)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: NFT not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
# NFT collection by ID
/cl2c/nft/{id}:
get:
tags:
- NFT
summary: Get NFT detail (includes copyright entries and per-owner info)
description: Retrieve a single NFT and its copyright/userNft entries. Ensures NFT belongs to the authenticated organization.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
description: NFT ID
responses:
'200':
description: NFT detail
content:
application/json:
schema:
$ref: '#/components/schemas/NFTDetail'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden (NFT does not belong to organization)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: NFT not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
tags:
- NFT
summary: Update NFT fields (name, description, status, mintedAt)
description: Update editable NFT fields. Only allowed when NFT status is not finalized (CREATED or PENDING). Status transitions are validated server-side.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateNFTbyID'
responses:
'200':
description: Updated NFT
content:
application/json:
schema:
$ref: '#/components/schemas/NFTSummary'
'400':
description: Bad request / invalid state (e.g., NFT already MINTED or ATTACHED)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden (NFT does not belong to your organization)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: NFT not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- NFT
summary: Delete an NFT
description: Delete an NFT record and its copyright entries. Only allowed when NFT status is not MINTED or ATTACHED.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
responses:
'200':
description: Deleted
content:
application/json:
schema:
type: object
properties:
message:
type: string
'400':
description: Bad request (e.g., cannot delete minted NFT)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden (NFT does not belong to your organization)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: NFT not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
# Token balance and transfer
/cl2c/token:
get:
tags:
- Tokens
summary: Get owner token balances
description: Returns owner token balance for a requested type, or both mainnet and faucet when type is omitted.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
- cookieAuth: []
parameters:
- in: query
name: type
required: false
schema:
type: string
enum: [mainnet, faucet]
description: When provided, returns a single balance object. If omitted, returns both balances.
responses:
'200':
description: Token balance response
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/TokenBalanceResponse'
- $ref: '#/components/schemas/TokenBalancesResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Tokens
summary: Send tokens to an organization member
description: Requires owner membership in the authenticated organization.
security:
- apiKeyAuth: []
- apiKeyBearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TokenSendRequest'
responses:
'200':
description: Tokens sent successfully
content:
application/json:
schema:
$ref: '#/components/schemas/TokenSendResponse'
'400':
description: Invalid request body or wallet configuration
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Only owners can send tokens
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Recipient or member not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server or token transfer error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'