Skip to main content

Keyban API Client

A Python client library for interacting with the Keyban API Product Sheet management. This client provides a clean, type-safe interface for managing product sheets, including full CRUD operations.

Features

  • List products with filtering and pagination
  • Get specific product sheets by ID (public endpoint)
  • Create new product sheets with validation
  • Update existing product sheets with partial updates
  • Delete product sheets with proper authorization
  • Type-safe models using Pydantic for request/response validation
  • Comprehensive error handling with proper HTTP status code handling
  • Convenience functions for common operations

Supported Network: Currently supports StarknetSepolia network only. This is set as default.

Quick Start

Simple Product Creation

from uuid import UUID
from keyban_api_client import ProductClient, ProductData, CreateProductRequest

# Initialize the client
client = ProductClient(
base_url="https://api.prod.keyban.io",
api_key="your-api-key"
)

# Create a simple product sheet (requires auth)
product_data = ProductData(
name="My Test Product",
description="A product created via Python client"
)

request = CreateProductRequest(
application=UUID("your-application-id"),
status="ACTIVE",
data=product_data,
certified_paths=["name", "description"]
)

new_sheet = client.create_product(request)
print(f"Created product sheet: {new_sheet.id}")

# List product sheets
sheets = client.list_products(page_size=10)
print(f"Found {sheets.total} product sheets")

# Get a specific product sheet (public endpoint - no auth needed)
sheet = client.get_product(new_sheet.id)
print(f"Product: {sheet.data.name}")

# Close the client when done
client.close()

Full Product Creation

from uuid import UUID
from keyban_api_client import ProductClient, ProductData, CreateProductRequest

# Initialize client
client = ProductClient(
base_url="https://api.prod.keyban.io",
api_key="your-api-key"
)

# Create a comprehensive product with custom fields
product_data = ProductData(
# Standard product fields
identifier="PROD-001",
name="Organic Cotton T-Shirt",
description="Sustainably produced cotton t-shirt",
image="https://example.com/product.jpg",
gtin="1234567890123",
sku="ECO-TS-M-BLU",
brand={
"name": "EcoWear",
"identifier": "ecowear-brand"
},
countryOfOrigin="TR", # Turkey
keywords=["organic", "cotton", "sustainable"],

# Custom fields via **{} syntax
**{
"material": "100% Organic Cotton",
"certification": "GOTS Certified",
"manufacturer": {
"name": "EcoTextiles Ltd",
"location": "Istanbul, Turkey"
}
}
)

# Create with certification
request = CreateProductRequest(
application=UUID("your-application-id"),
status="ACTIVE",
data=product_data,
certified_paths=[
"name", "brand", "gtin", "sku", "countryOfOrigin"
] # Only standard fields can be certified
)

sheet = client.create_product(request)
client.close()

Product Sheet Certification

Product sheets are certified on the blockchain using the certifiedPaths field. This field points to specific fields within product.data that will be digitally signed and recorded on the blockchain.

How Certification Works

  1. Certified Paths: The certifiedPaths field contains an array of JSON paths pointing to fields in the product data that should be certified
  2. Automatic Triggering: Certification events are automatically triggered when:
    • certifiedPaths field is updated
    • Any data field pointed to by certifiedPaths changes (during create or update operations)
    • Important: Certification is only triggered when the product sheet status is "active" (case-insensitive)
  3. Blockchain Event: A new blockchain event is emitted containing:
    • IPFS CID pointing to the certified data
    • Certifier signature
    • Product ID

Example: Creating a Product with Certification

from keyban_api_client import ProductData, CreateProductRequest

# Create product with standard structure + custom fields
product_data = ProductData(
# Standard base fields
identifier="PROD-001",
name="Organic Cotton T-Shirt",
description="Sustainably produced cotton t-shirt",
image="https://example.com/product.jpg",

# Standard product extension fields
gtin="1234567890123",
sku="ECO-TS-M-BLU",
brand={
"name": "EcoWear",
"identifier": "ecowear-brand",
"description": "Sustainable fashion brand"
},
countryOfOrigin="TR", # Turkey - converts to {"identifier": "TR"}
keywords=["organic", "cotton", "sustainable", "GOTS"],

# Custom domain-specific fields using **{} syntax
**{
"material": "100% Organic Cotton",
"certification": "GOTS Certified",
"manufacturer": {
"name": "EcoTextiles Ltd",
"location": "Istanbul, Turkey",
"certifications": ["GOTS", "OEKO-TEX"]
},
"sustainability": {
"carbonFootprint": "2.1 kg CO2",
"waterUsage": "2700L",
"recyclable": True
}
}
)

# Specify which fields should be certified on blockchain
# Standard product fields can be certified, custom fields are stored but not certified
request = CreateProductRequest(
application=your_app_id,
status="active",
data=product_data,
certified_paths=[
# Standard product fields (can be certified)
"identifier",
"name",
"description",
"image",
"gtin",
"sku",
"brand.name",
"brand.identifier",
"countryOfOrigin",
# Custom fields like "material", "certification" are stored via **{}
# Nested data like "manufacturer.*" is stored but cannot be certified yet (work in progress)
] # Only standard fields are blockchain-certified
)

# Create the product sheet - certification job will be automatically triggered
product = client.create_product(request)

# Later updates to certified fields will trigger new certification events
update_data = UpdateProductRequest(
data=ProductData(
name="Updated Standard Product",
description="Updated product description",
keywords=["updated", "product", "standard"]
),
certified_paths=["name", "description", "keywords"] # Re-certify updated fields
)
client.update_product(product.id, update_data)

Tracking Certifications

You can track product certifications using the Keyban indexer API:

curl 'https://subql-starknet-sepolia.prod.keyban.io/' \
-H 'accept: application/json' \
-H 'content-type: application/json' \
--data-raw '{
"query": "query CertificationEvents { productCertifications( filter: {productId: {equalTo: \"<productId>\"}} ) { edges { node { transactionId ipfsCid certifierPubkey certifierSignature } } } }",
"operationName": "CertificationEvents"
}'

Replace <productId> with your actual product sheet ID.

Advanced Usage

Advanced Filtering with FilterOperator

from keyban_api_client import FilterOperator

# Filter by application ID
app_filter = FilterOperator(field="application.id", operator="eq", value="your-app-id")

# Filter by product name (contains)
name_filter = FilterOperator(field="data.name", operator="contains", value="Cotton")

# Filter by status
status_filter = FilterOperator(field="status", operator="eq", value="ACTIVE")

# Use multiple filters
sheets = client.list_products(
filters=[app_filter, name_filter, status_filter],
page_size=20
)

print(f"Found {sheets.total} matching products")
for sheet in sheets.data:
print(f"- {sheet.data.name} ({sheet.status})")

Error Handling

import requests
from keyban_api_client import ProductClient

client = ProductClient(base_url="...", api_key="...")

try:
sheets = client.list_products()
except requests.HTTPError as e:
if e.response.status_code == 401:
print("Authentication failed")
elif e.response.status_code == 404:
print("Resource not found")
else:
print(f"HTTP error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")

Pagination

# Get all product sheets across multiple pages
all_sheets = []
page = 1
page_size = 50

while True:
response = client.list_products(
current_page=page,
page_size=page_size
)

all_sheets.extend(response.data)

# Check if we've got all sheets
if len(response.data) < page_size:
break

page += 1

print(f"Retrieved {len(all_sheets)} total product sheets")

Context Manager Usage

# Automatically close the session
with ProductClient(base_url="...", api_key="...") as client:
sheets = client.list_products()
# Client automatically closed when exiting the context

API Reference

ProductClient

Main client class for interacting with the API.

Constructor

ProductClient(
base_url: str,
api_version: str = "v1",
api_key: Optional[str] = None,
timeout: int = 30
)

Methods

list_products(application_id=None, name_filter=None, current_page=1, page_size=10)

List product sheets with optional filtering.

  • application_id (UUID, optional): Filter by application ID
  • name_filter (str, optional): Filter by product name (case-insensitive substring)
  • current_page (int): Page number (1-based, default: 1)
  • page_size (int): Items per page (default: 10, max: 100)

Returns: ProductListResponse with data (list of sheets) and total count.

get_product(product_id: UUID)

Get a specific product sheet by ID. This is a public endpoint.

Returns: Product object.

create_product(product_data: CreateProductRequest)

Create a new product sheet. Requires authentication.

Returns: Created Product object.

update_product(product_id: UUID, update_data: UpdateProductRequest)

Update an existing product sheet. Requires authentication and organization access.

Returns: Updated Product object.

delete_product(product_id: UUID)

Delete an existing product sheet. Requires authentication and organization-level access. Only product sheets belonging to the authenticated organization can be deleted.

Returns: bool - True if deletion was successful.

Data Models

Product

Main product sheet model with fields:

  • id: UUID
  • application: UUID
  • network: str (network enum value)
  • status: str (status enum value)
  • data: ProductData (product information)
  • certified_paths: Optional[List[str]] (blockchain-certified fields)
  • created_at: datetime
  • updated_at: datetime

ProductData

Product data following standard product format:

  • name: str (required)
  • description: Optional[str]
  • brand: Optional[str]
  • category: Optional[str]
  • Additional fields allowed (extra="allow")

CreateProductRequest

For creating new product sheets:

  • application: UUID (required)
  • network: str (required)
  • status: str (required)
  • data: ProductData (required)
  • certified_paths: Optional[List[str]]

UpdateProductRequest

For updating existing sheets (all fields optional):

  • network: Optional[str]
  • status: Optional[str]
  • data: Optional[ProductData]
  • certified_paths: Optional[List[str]]

API Endpoints Covered

This client covers the following endpoints from the Keyban API Product Sheet controller:

  • GET /v1/dpp/products - List product sheets
  • GET /v1/dpp/products/:id - Get product sheet by ID
  • POST /v1/dpp/products - Create product sheet
  • PATCH /v1/dpp/products/:id - Update product sheet
  • DELETE /v1/dpp/products/:id - Delete product sheet

License

This client is part of the DAP (Digital Asset Platform) by Keyban project.