Skip to main content

Overview

Product APIs enable you to create and manage your product catalog in MartianPay. A product represents an item or service you sell, supporting everything from simple products to complex items with multiple variants, subscription plans, and rich media.

What is a Product?

A product represents an item or service that you sell to your customers. Products can be simple items with fixed pricing, or complex items with multiple variants (such as different sizes, colors, or configurations). The Product API allows you to create, manage, and organize your product catalog with support for options, variants, media assets, and subscription plans.

Each product:

  • 🛍️ Represents an item or service for sale
  • 💰 Supports one-time purchases or subscriptions
  • 🎨 Has variants (size, color, etc.)
  • 📸 Includes media assets (images, videos)
  • 🏷️ Contains pricing and tax information
  • 🔄 Links to Payment Links for selling

🔗 Related APIs: Products are used with Payment Links, Subscriptions, and Payment Intents.

Key Features

FeatureDescription
Product VariantsSupport multiple variations (size, color, material)
Media ManagementAttach images and videos with ordering
Subscription SupportEnable recurring billing with selling plans
Tax IntegrationTax code support and address collection
Version ControlTrack changes with version numbers
Flexible PricingPer-variant pricing or fixed product pricing
MetadataCustom key-value pairs for your needs

Product Types

MartianPay supports various product configurations:

TypeDescriptionUse Case
Variant ProductsProducts with options (size, color) and multiple variantsMost e-commerce products (clothing, accessories)
Subscription ProductsRequires selling plan, recurring billing onlySaaS subscriptions, memberships
Hybrid ProductsSupports both one-time and subscription purchasesSoftware with one-time or monthly options

📌 Important: All products require options and variants. Simple products without variants are not supported.

Key Components

1. Product Types:

  • All products require options and variants (simple products without variants are not supported)
  • Complex products with options and variants (e.g., size, color)
  • Subscription-only products requiring selling plans
  • Products supporting both one-time and subscription purchases

2. Product Information:

  • Product information (name, description, pricing)
  • Options (e.g., Color, Size) with configurable values
  • Variants (combinations of option values)
  • Media assets (images, videos) with ordering
  • Selling plans for subscription billing
  • Tax codes and address collection settings

3. Version Control:

  • All products use version numbers for audit tracking
  • Optimistic locking prevents concurrent update conflicts
  • Historical snapshots allow rollback to previous versions

4. Typical Workflow:

  • Create products with options and variants
  • Associate media assets and selling plans
  • Update product configuration as needed
  • Manage active/inactive status
  • Delete inactive products when no longer needed

Product Structure

Hierarchy:

Product
├── Options (e.g., Size, Color)
│ └── Values (e.g., Small, Medium, Large)
├── Variants (combinations of option values)
│ ├── Variant 1: Small + Red
│ ├── Variant 2: Medium + Blue
│ └── Variant 3: Large + Red
├── Media Assets (images, videos)
└── Selling Plans (subscription options)

Use Cases

Common Scenarios:

  • 👕 Apparel: T-shirts with sizes (S, M, L) and colors
  • 📱 Electronics: Phones with storage options (64GB, 128GB, 256GB)
  • 💼 SaaS: Software with subscription tiers (Basic, Pro, Enterprise)
  • 🎮 Digital Goods: Games with edition variants (Standard, Deluxe, Ultimate)
  • 🛒 E-commerce: Any product with multiple options and pricing
  • 🎫 Events: Tickets with seating categories (VIP, Regular, Budget)

Best Practices

✅ DO:

  • Use clear, descriptive product names
  • Add high-quality media assets in the correct order
  • Specify accurate tax codes for compliance
  • Use metadata to link to your internal product IDs
  • Keep variants organized with logical option names
  • Enable address collection when shipping physical goods

❌ DON'T:

  • Create products without variants (not supported)
  • Use too many variants (keep it manageable)
  • Forget to set product as active when ready to sell
  • Mix unrelated options (e.g., "Color" with "Subscription Plan")
  • Leave descriptions empty (helps customers make decisions)

API Reference

2. Create Product

Creates a new product in your catalog. Supports simple products with fixed pricing or complex products with options and variants.

For detailed API reference, see: Create Product API

Request Parameters:

  • name (required): Name of the product
  • description (optional): Detailed description of the product
  • active (optional): Whether the product is currently available (default: true)
  • default_currency (optional): Base currency for the product/variants
  • collect_shipping_address (optional): Collect shipping address during checkout
  • collect_tax_address (optional): Collect billing/tax address during checkout
  • tax_code (optional): Tax classification code for the product
  • requires_selling_plan (optional): true=subscription only, false=one-time or subscription
  • metadata (optional): Additional custom data as key-value pairs
  • price (optional): Default price for simple products
  • fixed_price (optional): Fixed price override
  • media_order (optional): Array of media asset IDs in display order
  • options (optional): Array of product options (e.g., Color, Size)
  • variants (optional): Array of product variants
  • selling_plan_group_ids (optional): Associated selling plan groups for subscriptions

Request Example (Simple Product):

curl --location --request POST 'https://api.martianpay.com/v1/products' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic {BASE64_ENCODE(api_key + ":")}' \
--data-raw '{
"name": "Premium T-Shirt",
"description": "High-quality cotton t-shirt",
"active": true,
"default_currency": "USD",
"price": {
"amount": 29.99,
"asset_id": "USD"
},
"collect_shipping_address": true,
"collect_tax_address": true,
"tax_code": "txcd_99999999",
"metadata": {
"category": "apparel",
"sku": "TSHIRT-001"
}
}'

Request Example (Product with Variants):

curl --location --request POST 'https://api.martianpay.com/v1/products' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic {BASE64_ENCODE(api_key + ":")}' \
--data-raw '{
"name": "Premium T-Shirt",
"description": "High-quality cotton t-shirt in multiple sizes and colors",
"active": true,
"default_currency": "USD",
"collect_shipping_address": true,
"collect_tax_address": true,
"options": [
{
"name": "Size",
"sort_order": 1,
"values": [
{
"value": "Small",
"sort_order": 1
},
{
"value": "Medium",
"sort_order": 2
},
{
"value": "Large",
"sort_order": 3
}
]
},
{
"name": "Color",
"sort_order": 2,
"values": [
{
"value": "Black",
"sort_order": 1,
"swatch": {
"type": "color",
"value": "#000000"
}
},
{
"value": "White",
"sort_order": 2,
"swatch": {
"type": "color",
"value": "#FFFFFF"
}
}
]
}
],
"variants": [
{
"active": true,
"option_values": {
"Size": "Small",
"Color": "Black"
},
"price": {
"amount": 29.99,
"asset_id": "USD"
},
"inventory_quantity": 100
},
{
"active": true,
"option_values": {
"Size": "Medium",
"Color": "Black"
},
"price": {
"amount": 29.99,
"asset_id": "USD"
},
"inventory_quantity": 150
},
{
"active": true,
"option_values": {
"Size": "Large",
"Color": "White"
},
"price": {
"amount": 32.99,
"asset_id": "USD"
},
"inventory_quantity": 75
}
],
"metadata": {
"category": "apparel",
"brand": "Premium Basics"
}
}'

Response:

{
"error_code": "success",
"msg": "success",
"data": {
"id": "prod_abc123xyz",
"name": "Premium T-Shirt",
"description": "High-quality cotton t-shirt in multiple sizes and colors",
"active": true,
"default_currency": "USD",
"created_at": 1701234567,
"updated_at": 1701234567,
"version": 1,
"collect_shipping_address": true,
"collect_tax_address": true,
"tax_code": "txcd_99999999",
"requires_selling_plan": false,
"selling_plan_group_ids": [],
"metadata": {
"category": "apparel",
"brand": "Premium Basics"
},
"media_order": [],
"options": [
{
"name": "Size",
"sort_order": 1,
"metadata": {},
"values": [
{
"value": "Small",
"sort_order": 1,
"metadata": {}
},
{
"value": "Medium",
"sort_order": 2,
"metadata": {}
},
{
"value": "Large",
"sort_order": 3,
"metadata": {}
}
]
},
{
"name": "Color",
"sort_order": 2,
"metadata": {},
"values": [
{
"value": "Black",
"sort_order": 1,
"metadata": {},
"swatch": {
"type": "color",
"value": "#000000"
}
},
{
"value": "White",
"sort_order": 2,
"metadata": {},
"swatch": {
"type": "color",
"value": "#FFFFFF"
}
}
]
}
],
"variants": [
{
"id": "var_123",
"active": true,
"version": 1,
"inventory_quantity": 100,
"option_values": {
"Size": "Small",
"Color": "Black"
},
"price": {
"amount": 29.99,
"asset_id": "USD"
},
"media_order": [],
"selling_plan_group_ids": []
},
{
"id": "var_124",
"active": true,
"version": 1,
"inventory_quantity": 150,
"option_values": {
"Size": "Medium",
"Color": "Black"
},
"price": {
"amount": 29.99,
"asset_id": "USD"
},
"media_order": [],
"selling_plan_group_ids": []
},
{
"id": "var_125",
"active": true,
"version": 1,
"inventory_quantity": 75,
"option_values": {
"Size": "Large",
"Color": "White"
},
"price": {
"amount": 32.99,
"asset_id": "USD"
},
"media_order": [],
"selling_plan_group_ids": []
}
],
"includes": {
"media": []
},
"selling_plan_groups": []
}
}

Important Notes:

  1. Version Control: The product is created with version: 1. Always include the current version number when updating.

  2. Options and Variants:

    • Options define the configurable attributes (e.g., Size, Color)
    • Variants represent specific combinations of option values
    • Each variant must have a unique combination of option values
    • All products must have options and variants - simple products without variants are not supported
    • Complete variant coverage required: You must provide variants for all possible combinations of option values (Cartesian product)
  3. Variant Required Fields:

    • price is required for each variant - variants without pricing will be rejected (Error code 223: variant_price_required)
    • inventory_quantity is required for each variant - variants without inventory will be rejected (Error code 224: variant_inventory_required)
    • Ensure all variants include both fields to avoid validation errors
  4. Pricing:

    • The price field at the product level is optional and serves as a default
    • Each variant must have its own price field specified
    • Prices are specified with amount and asset_id (currency)
  5. Inventory: The inventory_quantity field is required for all variants and is used to track stock levels.

  6. Subscriptions: Set requires_selling_plan: true to make a product subscription-only. Associate selling plan groups using selling_plan_group_ids.

  7. Metadata: Use metadata to store custom information like SKU, category, brand, or any other data relevant to your business.

Understanding the Response

How to Check if the Request Was Successful:

FieldValueMeaning
error_code"success"✅ Product created successfully
error_code"invalid_request_error"❌ Invalid product configuration or variant setup
error_code"variant_price_required"❌ All variants must have a price specified (Error 223)
error_code"variant_inventory_required"❌ All variants must have inventory_quantity specified (Error 224)
error_code"variants_incomplete"❌ Variants don't cover all option combinations (Error 235)
error_codeOther value❌ Other error occurred

Key Fields:

FieldDescription
idUnique product identifier (use for updates, payouts, payment links)
versionProduct version number (starts at 1, increment on updates)
activeWhether product is available for sale
variantsArray of product variants with unique id for each
optionsProduct configuration options (Size, Color, etc.)
media_orderOrdered list of media asset IDs
selling_plan_group_idsAssociated subscription plans

Version Control:

  • Product created with version: 1
  • MUST include version number when updating
  • Version increments automatically on updates
  • Enables optimistic locking to prevent conflicts

Variant Structure:

  • Each variant gets a unique id (e.g., "var_123")
  • All variants have version: 1 initially
  • Required fields: price and inventory_quantity
  • Complete coverage: Must provide variants for ALL option combinations

Common Errors and Solutions:

Error CodeProblemSolution
223 (variant_price_required)Missing variant priceAdd price field to all variants
224 (variant_inventory_required)Missing inventory quantityAdd inventory_quantity to all variants
235 (variants_incomplete)Incomplete variant combinationsProvide variants for all option combinations (Cartesian product)

Next Steps:

  • Save the product id for use in payment links and payment intents
  • Note the version number for future updates
  • Add media assets using Media API and update media_order
  • Create selling plan groups if offering subscriptions
  • Use variant id values when processing orders
  • Set active: true when ready to sell

3. List Products

Retrieves a paginated list of products from your catalog. Supports filtering by active status.

For detailed API reference, see: List Products API

Request:

curl --location --request GET 'https://api.martianpay.com/v1/products?page=0&page_size=10&active=true' \
--header 'Authorization: Basic {BASE64_ENCODE(api_key + ":")}'

Query Parameters:

  • page (optional): Page number, zero-based (default: 0)
  • page_size (optional): Items per page, 1-50 (default: 10)
  • active (optional): Filter by active status (true=active, false=inactive)

Response:

{
"error_code": "success",
"msg": "success",
"data": {
"page": 0,
"page_size": 10,
"total": 25,
"products": [
{
"id": "prod_abc123xyz",
"name": "Premium T-Shirt",
"description": "High-quality cotton t-shirt in multiple sizes and colors",
"active": true,
"default_currency": "USD",
"created_at": 1701234567,
"updated_at": 1701234567,
"version": 1,
"collect_shipping_address": true,
"collect_tax_address": true,
"tax_code": "txcd_99999999",
"requires_selling_plan": false,
"selling_plan_group_ids": [],
"metadata": {
"category": "apparel",
"brand": "Premium Basics"
},
"price": {
"amount": 29.99,
"asset_id": "USD"
},
"media_order": ["media_001", "media_002"],
"options": [
{
"name": "Size",
"sort_order": 1,
"values": [
{
"value": "Small",
"sort_order": 1
},
{
"value": "Medium",
"sort_order": 2
}
]
}
],
"variants": [
{
"id": "var_123",
"active": true,
"version": 1,
"inventory_quantity": 100,
"option_values": {
"Size": "Small"
},
"price": {
"amount": 29.99,
"asset_id": "USD"
},
"media_order": []
}
],
"includes": {
"media": [
{
"id": "media_001",
"url": "https://cdn.example.com/image1.jpg",
"content_type": "image/jpeg",
"alt_text": "Premium T-Shirt Front View",
"width": 1200,
"height": 1600
}
]
},
"selling_plan_groups": []
}
]
}
}

Important Notes:

  1. Pagination: Use page and page_size to navigate through large product catalogs. The total field shows the total number of products matching the filter.

  2. Filtering: Use the active parameter to show only active or inactive products. Omit this parameter to retrieve all products.

  3. Expanded Data: The response includes expanded variants, media assets, and selling plan groups for convenience.

  4. Media Assets: Product images and videos are returned in the includes.media array, ordered according to media_order.

Understanding the Response

How to Check if the Request Was Successful:

FieldValueMeaning
error_code"success"✅ Products retrieved successfully
error_codeOther value❌ Error occurred

Key Fields:

  • products: Array of product objects
  • total: Total number of products matching the filter
  • page: Current page number (0-based)
  • page_size: Number of items per page

Pagination:

  • Use page and page_size to navigate through results
  • If total > page_size, there are more pages available
  • Next page: increase page by 1

Filtering:

  • active=true: Show only active products
  • active=false: Show only inactive products
  • Omit active: Show all products

Expanded Data: Response includes complete product details:

  • Full variant information with prices and inventory
  • Media assets in includes.media array
  • Selling plan groups if product has subscriptions
  • Options and their values

Product Status:

active FieldMeaningUse Case
true✅ Available for saleShow in storefront, accept orders
false❌ Not availableHidden from customers, no sales

Next Steps:

  • Loop through products array to display catalog
  • Use product id for details, updates, or payment links
  • Check active status before showing to customers
  • Filter by active: true for customer-facing catalogs
  • Use pagination for large product lists

4. Get Product

Retrieves comprehensive information about a specific product, including all variants, options, pricing, media assets, and metadata.

For detailed API reference, see: Get Product API

Request:

curl --location --request GET 'https://api.martianpay.com/v1/products/prod_abc123xyz' \
--header 'Authorization: Basic {BASE64_ENCODE(api_key + ":")}'

Request (Get Specific Version):

curl --location --request GET 'https://api.martianpay.com/v1/products/prod_abc123xyz?version=2' \
--header 'Authorization: Basic {BASE64_ENCODE(api_key + ":")}'

Query Parameters:

  • version (optional): Retrieve a specific historical version of the product

Response:

{
"error_code": "success",
"msg": "success",
"data": {
"id": "prod_abc123xyz",
"name": "Premium T-Shirt",
"description": "High-quality cotton t-shirt in multiple sizes and colors",
"active": true,
"default_currency": "USD",
"created_at": 1701234567,
"updated_at": 1701345678,
"version": 3,
"collect_shipping_address": true,
"collect_tax_address": true,
"tax_code": "txcd_99999999",
"requires_selling_plan": false,
"selling_plan_group_ids": ["spg_001"],
"metadata": {
"category": "apparel",
"brand": "Premium Basics",
"featured": "true"
},
"price": {
"amount": 29.99,
"asset_id": "USD"
},
"fixed_price": null,
"media_order": ["media_001", "media_002", "media_003"],
"options": [
{
"name": "Size",
"sort_order": 1,
"metadata": {},
"values": [
{
"value": "Small",
"sort_order": 1,
"metadata": {}
},
{
"value": "Medium",
"sort_order": 2,
"metadata": {}
},
{
"value": "Large",
"sort_order": 3,
"metadata": {}
}
]
},
{
"name": "Color",
"sort_order": 2,
"metadata": {},
"values": [
{
"value": "Black",
"sort_order": 1,
"metadata": {},
"swatch": {
"type": "color",
"value": "#000000"
}
},
{
"value": "White",
"sort_order": 2,
"metadata": {},
"swatch": {
"type": "color",
"value": "#FFFFFF"
}
}
]
}
],
"variants": [
{
"id": "var_123",
"active": true,
"version": 3,
"inventory_quantity": 85,
"option_values": {
"Size": "Small",
"Color": "Black"
},
"price": {
"amount": 29.99,
"asset_id": "USD"
},
"media_order": ["media_001"],
"selling_plan_group_ids": ["spg_001"],
"selling_plan_groups": [
{
"id": "spg_001",
"name": "Monthly Subscription",
"description": "Subscribe and save 10%",
"status": "active",
"options": ["1 month"],
"selling_plans": [
{
"id": "sp_001",
"name": "Monthly Plan",
"description": "Billed monthly",
"status": "active",
"billing_policy_type": "RECURRING",
"billing_policy": {},
"pricing_policy": [],
"priority": "1",
"trial_period_days": "7",
"created_at": 1701234567,
"updated_at": 1701234567,
"valid_from": 1701234567,
"valid_until": 1735689600,
"version": 1
}
]
}
],
"selling_plan_pricing": [
{
"selling_plan_id": "sp_001",
"selling_plan_name": "Monthly Plan",
"billing_cycle": "month",
"currency": "USD",
"trial_period_days": 7,
"pricing_tiers": [
{
"policy_type": "RECURRING",
"after_cycle": 1,
"cycle_description": "Cycle 1 onwards",
"total_cycles": 0,
"base_price": "29.99",
"selling_plan_discount": "3.00",
"subtotal_before_policy": "29.99",
"subtotal_after_policy": "26.99"
}
]
}
]
}
],
"includes": {
"media": [
{
"id": "media_001",
"url": "https://cdn.example.com/tshirt-front.jpg",
"content_type": "image/jpeg",
"alt_text": "Premium T-Shirt Front View",
"width": 1200,
"height": 1600
},
{
"id": "media_002",
"url": "https://cdn.example.com/tshirt-back.jpg",
"content_type": "image/jpeg",
"alt_text": "Premium T-Shirt Back View",
"width": 1200,
"height": 1600
},
{
"id": "media_003",
"url": "https://cdn.example.com/tshirt-detail.jpg",
"content_type": "image/jpeg",
"alt_text": "Premium T-Shirt Fabric Detail",
"width": 1200,
"height": 1200
}
]
},
"selling_plan_groups": [
{
"id": "spg_001",
"name": "Monthly Subscription",
"description": "Subscribe and save 10%",
"status": "active",
"options": ["1 month"],
"selling_plans": [
{
"id": "sp_001",
"name": "Monthly Plan",
"description": "Billed monthly",
"status": "active",
"billing_policy_type": "RECURRING",
"billing_policy": {},
"pricing_policy": [],
"priority": "1",
"trial_period_days": "7",
"created_at": 1701234567,
"updated_at": 1701234567,
"valid_from": 1701234567,
"valid_until": 1735689600,
"version": 1
}
]
}
]
}
}

Important Notes:

  1. Version History: Use the version query parameter to retrieve historical snapshots of the product. This is useful for auditing changes or rolling back to a previous version.

  2. Expanded Data: The response includes complete details about:

    • All variants with their prices and inventory
    • Media assets with URLs and metadata
    • Selling plan groups and pricing tiers
    • Subscription pricing calculations
  3. Selling Plans: For subscription products, the response includes:

    • Product-level selling plan groups
    • Variant-level selling plan associations
    • Detailed pricing tiers showing discounts and final prices
    • Trial period information
  4. Media Assets: Images and videos are ordered according to media_order for consistent display across your storefront.

Understanding the Response

How to Check if the Request Was Successful:

FieldValueMeaning
error_code"success"✅ Product retrieved successfully
error_code"product_not_found"❌ No product exists with this ID
error_codeOther value❌ Other error occurred

Key Product Information:

FieldDescription
idProduct identifier
versionCurrent version number (for updates)
activeWhether product is available for sale
variantsComplete variant details with pricing and inventory
optionsProduct configuration options
media_orderOrdered media asset IDs
selling_plan_groupsSubscription plans (if applicable)

Version History:

  • Use ?version=N query parameter to retrieve specific historical version
  • Useful for auditing changes or rollback scenarios
  • Current version shown in response

Expanded Details: The response includes complete information:

  • Variants: Full details with prices, inventory, and variant-specific data
  • Media Assets: Images and videos in includes.media with URLs
  • Selling Plans: Subscription pricing tiers and trial periods
  • Selling Plan Pricing: Calculated pricing for each subscription tier

Subscription Product Information: For products with subscriptions:

  • selling_plan_groups: Available subscription plans
  • selling_plan_pricing: Pricing breakdown per variant and plan
  • trial_period_days: Free trial duration
  • pricing_tiers: Cycle-by-cycle pricing with discounts

Next Steps:

  • Note the version number for updates
  • Use variant id values when creating payment intents
  • Check active status before showing to customers
  • Display media from includes.media in your UI
  • Show subscription pricing if selling_plan_groups is present

5. Update Product

Updates an existing product with version control. All changes increment the product version for audit tracking. You can update product details, pricing, variants, options, active status, and media.

For detailed API reference, see: Update Product API

Request:

curl --location --request POST 'https://api.martianpay.com/v1/products/prod_abc123xyz' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic {BASE64_ENCODE(api_key + ":")}' \
--data-raw '{
"version": 3,
"name": "Premium T-Shirt - Updated",
"description": "High-quality organic cotton t-shirt in multiple sizes and colors",
"active": true,
"price": {
"amount": 34.99,
"asset_id": "USD"
},
"metadata": {
"category": "apparel",
"brand": "Premium Basics",
"featured": "true",
"organic": "true"
},
"variants": [
{
"id": "var_123",
"active": true,
"option_values": {
"Size": "Small",
"Color": "Black"
},
"price": {
"amount": 34.99,
"asset_id": "USD"
},
"inventory_quantity": 85
}
]
}'

Request (Deactivate Product):

curl --location --request POST 'https://api.martianpay.com/v1/products/prod_abc123xyz' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic {BASE64_ENCODE(api_key + ":")}' \
--data-raw '{
"version": 3,
"active": false
}'

Response:

{
"error_code": "success",
"msg": "success",
"data": {
"id": "prod_abc123xyz",
"name": "Premium T-Shirt - Updated",
"description": "High-quality organic cotton t-shirt in multiple sizes and colors",
"active": true,
"default_currency": "USD",
"created_at": 1701234567,
"updated_at": 1701456789,
"version": 4,
"collect_shipping_address": true,
"collect_tax_address": true,
"tax_code": "txcd_99999999",
"requires_selling_plan": false,
"selling_plan_group_ids": ["spg_001"],
"metadata": {
"category": "apparel",
"brand": "Premium Basics",
"featured": "true",
"organic": "true"
},
"price": {
"amount": 34.99,
"asset_id": "USD"
},
"media_order": ["media_001", "media_002", "media_003"],
"options": [
{
"name": "Size",
"sort_order": 1,
"values": [
{
"value": "Small",
"sort_order": 1
}
]
},
{
"name": "Color",
"sort_order": 2,
"values": [
{
"value": "Black",
"sort_order": 1,
"swatch": {
"type": "color",
"value": "#000000"
}
}
]
}
],
"variants": [
{
"id": "var_123",
"active": true,
"version": 4,
"inventory_quantity": 85,
"option_values": {
"Size": "Small",
"Color": "Black"
},
"price": {
"amount": 34.99,
"asset_id": "USD"
},
"media_order": [],
"selling_plan_group_ids": []
}
],
"includes": {
"media": []
},
"selling_plan_groups": []
}
}

Important Notes:

  1. Version Requirement: You MUST include the current version number in your update request. This implements optimistic locking to prevent concurrent update conflicts.

  2. Version Mismatch Error: If the version number doesn't match the current product version, you'll receive a 409 Conflict error. Fetch the latest product data and retry with the correct version.

  3. Incremented Version: On successful update, the product version is incremented (from 3 to 4 in the example above).

  4. Partial Updates: You can update specific fields without providing all product data. However, when updating arrays (like variants), provide the complete array with all items.

  5. Active Status: Set active: false to deactivate a product. Inactive products won't appear in payment links or customer-facing catalogs.

  6. Variant Updates: When updating variants, include the variant id for existing variants. Variants without an id will be created as new variants.

  7. Metadata Updates: Metadata is merged, not replaced. To remove a metadata key, explicitly set its value to null or empty string.

Error Responses:

{
"code": 400,
"error_code": "invalid_request_error",
"msg": "Invalid product configuration or variant setup"
}
{
"code": 409,
"error_code": "version_conflict",
"msg": "Version conflict - product was modified by another request"
}

Variant Validation Error Codes:

{
"code": 223,
"error_code": "variant_price_required",
"msg": "All variants must have a price specified"
}
{
"code": 224,
"error_code": "variant_inventory_required",
"msg": "All variants must have inventory_quantity specified"
}
{
"code": 235,
"error_code": "variants_incomplete",
"msg": "Product variants do not cover all possible option combinations. Please provide variants for all combinations of option values (Cartesian product)."
}

Understanding the Response

How to Check if the Request Was Successful:

FieldValueMeaning
error_code"success"✅ Product updated successfully
error_code"invalid_request_error"❌ Invalid product configuration or variant setup
error_code"version_conflict"❌ Version mismatch - product was modified by another request (409)
error_code"variant_price_required"❌ Missing variant price (Error 223)
error_code"variant_inventory_required"❌ Missing inventory quantity (Error 224)
error_code"variants_incomplete"❌ Incomplete variant combinations (Error 235)
error_codeOther value❌ Other error occurred

Key Update Indicators:

FieldWhat Changed
versionIncremented from old version to new version
updated_atTimestamp updated to reflect modification time
Modified fieldsReflect your changes (name, price, variants, etc.)

Version Control:

  • MUST provide current version: Include version field matching current product version
  • Version incremented: New version = old version + 1 (e.g., 3 → 4)
  • Optimistic Locking: Prevents concurrent update conflicts
  • 409 Conflict Error: If version mismatch, fetch latest and retry

What You Can Update:

  • ✅ Product details (name, description, metadata)
  • ✅ Pricing (product-level or variant-level)
  • ✅ Variants (add new, update existing, deactivate)
  • ✅ Active status (activate or deactivate product)
  • ✅ Media order
  • ✅ Selling plan associations
  • ❌ Cannot change product id

Partial vs Complete Updates:

  • Update specific fields without providing all data
  • Exception: When updating arrays (variants), provide complete array
  • Metadata is merged, not replaced

Active Status Updates:

  • Set active: false to deactivate (hide from customers)
  • Set active: true to activate (show to customers)
  • Omit field to leave status unchanged

Variant Updates:

  • Include variant id for existing variants
  • Variants without id are created as new
  • Must include: price and inventory_quantity for all variants
  • Must provide: Complete variant coverage for all option combinations

Common Errors:

ErrorCodeSolution
Version conflict409Fetch latest product, retry with correct version
Missing price223Add price to all variants
Missing inventory224Add inventory_quantity to all variants
Incomplete variants235Provide variants for all option combinations

Next Steps:

  • Note the new version number for future updates
  • Verify changes in response match your request
  • If 409 error, fetch latest version and retry
  • Test updated product in payment links/intents
  • Update product version in your local cache/database

6. Delete Product

Soft-deletes an inactive product from your catalog. Only inactive products that are not used in any payment links can be deleted. Product data is retained for historical records but marked as deleted.

For detailed API reference, see: Delete Product API

Request:

curl --location --request DELETE 'https://api.martianpay.com/v1/products/prod_abc123xyz' \
--header 'Authorization: Basic {BASE64_ENCODE(api_key + ":")}'

Response:

{
"error_code": "success",
"msg": "success",
"data": {
"deleted": true,
"id": "prod_abc123xyz"
}
}

Important Notes:

  1. Inactive Products Only: You can only delete products that have active: false. Set a product to inactive first, then delete it.

  2. Not in Use: Products that are currently used in active payment links cannot be deleted. Remove the product from all payment links first.

  3. Soft Delete: This is a soft delete operation. The product data is retained in the database for historical records and audit purposes, but marked as deleted.

  4. Cannot Be Undone: Once deleted, a product cannot be restored. You would need to create a new product with the same details.

  5. Historical References: Deleted products remain visible in historical payment intents, invoices, and subscriptions for record-keeping.

Error Responses:

{
"code": 400,
"error_code": "invalid_request_error",
"msg": "Cannot delete active product. Set active=false first."
}
{
"code": 400,
"error_code": "invalid_request_error",
"msg": "Cannot delete product that is used in active payment links"
}
{
"code": 404,
"error_code": "resource_not_found",
"msg": "Product not found"
}

Understanding the Response

How to Check if the Request Was Successful:

FieldValueMeaning
error_code"success"✅ Product deleted successfully
error_code"invalid_request_error"❌ Cannot delete (product is active or in use)
error_code"resource_not_found"❌ Product not found (404)
error_codeOther value❌ Other error occurred

Success Response:

FieldDescription
deletedtrue = product successfully deleted
idID of the deleted product

Deletion Requirements:

RequirementCheck
Product must be inactiveSet active: false before deleting
Not used in payment linksRemove from all payment links first
Not used in active subscriptionsEnsure no active subscriptions reference this product

What Happens:

  • ✅ Product marked as deleted in database
  • ✅ No longer appears in product lists
  • ✅ Cannot be used for new payments or payment links
  • ✅ Historical data retained for auditing
  • Cannot be undone - deletion is permanent

Common Deletion Errors:

ErrorReasonSolution
Cannot delete active productProduct has active: trueUpdate product with active: false first
Cannot delete (in use)Product used in payment linksRemove from all payment links
Product not found (404)Invalid product IDVerify product ID is correct

Soft Delete vs Hard Delete:

  • Soft Delete: Product data retained in database but marked as deleted
  • Visible in History: Still appears in historical payment intents, orders, subscriptions
  • Cannot Be Restored: No API to restore deleted products
  • Recreate if Needed: Create new product with same details if needed

Alternatives to Deletion:

  • Deactivate Instead: Set active: false to hide from customers while preserving product
  • Keep for History: Leave inactive products for historical reference
  • Only Delete: When product is truly obsolete and not referenced

Next Steps:

  • Confirm product is deleted using List Products API
  • Update any internal systems that referenced this product ID
  • If you need this product again, create a new one (cannot restore)
  • Review payment links to ensure they don't reference deleted product

Best Practices

  1. Version Control:

    • Always fetch the latest product before updating to get the current version number
    • Handle 409 Conflict errors by refetching and retrying with the updated version
    • Use version history to audit changes and rollback if needed
  2. Product Organization:

    • Use meaningful product names and descriptions for easy identification
    • Leverage metadata to categorize and tag products (e.g., category, brand, SKU)
    • Organize media assets in a logical order for consistent display
  3. Variants Management:

    • All products must have options and variants - simple products are not supported
    • Create options and variants for products with multiple configurations
    • Use descriptive option names (Size, Color, Material) and values
    • Ensure complete coverage: Provide variants for all possible combinations of option values (Cartesian product)
    • Always specify price for each variant (required field)
    • Always specify inventory_quantity for each variant (required field)
    • Track inventory at the variant level for accurate stock management
  4. Pricing Strategy:

    • Product-level price is optional and serves as a default
    • Each variant must have its own price specified - this is a required field
    • Use selling plans to offer subscription discounts
    • Consider using fixed_price for promotional pricing
  5. Media Assets:

    • Upload high-quality product images for better conversion
    • Use descriptive alt_text for accessibility
    • Order media assets using media_order for consistent display
    • Attach variant-specific images when applicable
  6. Subscription Products:

    • Set requires_selling_plan: true for subscription-only products
    • Associate appropriate selling plan groups at product or variant level
    • Clearly communicate subscription terms in product descriptions
    • Use trial periods to encourage subscription adoption
  7. Active Status Management:

    • The active field behavior during updates: omitting the field (nil) = no change, true = activate, false = deactivate
    • The same behavior applies to variant active fields
    • Set products/variants to inactive instead of deleting when temporarily unavailable
    • Keep historical products inactive for record-keeping
    • Only delete products that are truly obsolete and not referenced anywhere
  8. Tax and Shipping:

    • Set appropriate tax codes for tax calculation
    • Enable address collection when shipping products
    • Use collect_tax_address for accurate tax calculations
  9. Testing:

    • Test product creation with various option and variant combinations
    • Verify pricing calculations, especially for subscription products
    • Test with both simple and complex product configurations
    • Validate media asset display on your storefront
  10. Error Handling:

    • Implement retry logic for version conflicts
    • Validate product data before submission
    • Handle error responses gracefully in your application
    • Log errors for debugging and monitoring