ServiceOffering API Reference
Complete API reference for the ServiceOffering type, including marketplace listing methods and properties
The $.ServiceOffering type represents a public marketplace listing for a service. It contains marketing information, pricing, visibility settings, and everything needed to make a service discoverable and purchasable in the marketplace.
Type Definition
// @errors: 7006
interface ServiceOffering extends Thing {
$type: 'ServiceOffering'
$id: string
service: Service
// ^^^^^^^
title: string
description: string
longDescription?: string
images?: string[]
featured: boolean
visibility: OfferingVisibility
// ^^^^^^^^^^^^^^^^^^^
pricing: PricingSpecification
category: string
tags?: string[]
rating?: number
reviewCount?: number
orderCount?: number
highlights?: string[]
benefits?: string[]
features?: string[]
testimonials?: Testimonial[]
callToAction?: CallToAction
restrictions?: OfferingRestrictions
seo?: SEOMetadata
metadata?: OfferingMetadata
}
type OfferingVisibility = 'public' | 'private' | 'unlisted'
// ^^^^^^^^
interface Testimonial {
quote: string
author: string
title: string
company: string
image?: string
}
interface CallToAction {
text: string
url?: string
action?: string
}
interface OfferingRestrictions {
regions?: string[]
industries?: string[]
minOrderSize?: number
maxOrderSize?: number
requiresApproval?: boolean
//^^^^^^^^^^^^^^^^^
}
interface SEOMetadata {
metaTitle?: string
metaDescription?: string
keywords?: string[]
slug?: string
}
interface OfferingMetadata {
createdAt: string
updatedAt: string
publishedAt?: string
lastOrderAt?: string
}
const offering: ServiceOffering = {
// ^?
$type: 'ServiceOffering',
$id: 'offering-123',
service: {} as Service,
title: 'AI SDR Professional',
description: 'Automated outreach at scale',
featured: true,
visibility: 'public',
pricing: {} as PricingSpecification,
category: 'sales',
}Properties
Core Properties
service
- Type:
Service - Required: Yes
- Description: The underlying service being offered
- Pattern:
$.ServiceOffering[id].service -> $.Service[serviceId] - Example:
$.Service.get('service-123')
title
- Type:
string - Required: Yes
- Description: Marketing title for the offering
- Example:
'AI-Powered SDR Outreach - Professional Plan' - Constraints: 10-200 characters
description
- Type:
string - Required: Yes
- Description: Short marketing description
- Example:
'Let our AI handle your outreach while you focus on closing deals' - Constraints: 50-500 characters
longDescription
- Type:
string - Required: No
- Description: Extended marketing description with full details
- Format: Markdown supported
- Example: Multi-paragraph description with formatting
images
- Type:
string[] - Required: No
- Description: Array of image URLs for the offering
- Example:
['https://cdn.example.com/hero.jpg', 'https://cdn.example.com/screenshot.png'] - Constraints: Max 10 images, supported formats: JPG, PNG, WebP
featured
- Type:
boolean - Required: No
- Default:
false - Description: Whether this offering is featured in the marketplace
visibility
- Type:
OfferingVisibility - Required: Yes
- Default:
'public' - Values:
'public' | 'private' | 'unlisted' - Description: Visibility level of the offering
public: Visible to all users in marketplaceprivate: Only visible to specific customersunlisted: Accessible via direct link only
Pricing Properties
pricing
- Type:
PricingSpecification - Required: Yes
- Description: Public pricing for this offering
- Properties:
model: Pricing model typeamount: Base pricecurrency: ISO 4217 currency codeperiod: Billing period (for subscriptions)discount: Optional discount information
Marketing Properties
highlights
- Type:
string[] - Required: No
- Description: Key highlights or bullet points
- Example:
['10x faster than manual outreach', '99% deliverability', '24/7 AI monitoring']
benefits
- Type:
string[] - Required: No
- Description: Customer benefits
- Example:
['Save 20 hours per week', 'Generate 50% more qualified leads']
features
- Type:
string[] - Required: No
- Description: Feature list
- Example:
['AI-powered personalization', 'Multi-channel outreach', 'Real-time analytics']
testimonials
- Type:
Testimonial[] - Required: No
- Description: Customer testimonials with author info
callToAction
- Type:
CallToAction - Required: No
- Description: Primary call-to-action button
- Properties:
text: Button text (e.g., 'Start Free Trial')url: External URL (optional)action: Internal action (e.g., 'start-trial')
Computed Properties
rating
- Type:
number - Required: No
- Computed: Yes
- Description: Average customer rating (0-5)
- Example:
4.7
reviewCount
- Type:
number - Required: No
- Computed: Yes
- Description: Total number of reviews
- Example:
142
orderCount
- Type:
number - Required: No
- Computed: Yes
- Description: Total number of orders
- Example:
1547
SEO Properties
seo
- Type:
SEOMetadata - Required: No
- Description: Search engine optimization metadata
- Properties:
metaTitle: SEO title tagmetaDescription: SEO meta descriptionkeywords: Target keywordsslug: URL-friendly slug
Methods
create()
Create a new marketplace offering.
Signature:
$.ServiceOffering.create(config: OfferingConfig): Promise<ServiceOffering>Parameters:
config: Offering configuration object
Returns: Promise resolving to the created ServiceOffering
Example:
const offering = await $.ServiceOffering.create({
service: $.Service.get('service-id'),
title: 'AI-Powered SDR Outreach - Professional Plan',
description: 'Let our AI handle your outreach while you focus on closing deals.',
longDescription: `
# Transform Your Sales Outreach
Our AI-powered SDR service handles the entire outreach process...
## What You Get
- Personalized messaging for each lead
- Multi-channel outreach (email, LinkedIn, phone)
- Real-time analytics and reporting
`,
images: ['https://cdn.example.com/hero.jpg', 'https://cdn.example.com/dashboard.png'],
featured: true,
visibility: 'public',
pricing: {
model: 'per-lead',
amount: 5,
currency: 'USD',
},
category: 'sales',
tags: ['ai', 'sdr', 'outreach', 'b2b'],
})get()
Retrieve an offering by ID.
Signature:
$.ServiceOffering.get(id: string): Promise<ServiceOffering>Parameters:
id: Offering identifier
Returns: Promise resolving to the ServiceOffering
Example:
const offering = await $.ServiceOffering.get('offering-123')
console.log(offering.title)
console.log(offering.pricing)list()
List all offerings with optional filtering.
Signature:
$.ServiceOffering.list(filter?: OfferingFilter): Promise<ServiceOffering[]>Parameters:
filter: Optional filter criteria
Returns: Promise resolving to array of ServiceOfferings
Example:
// List all public offerings
const publicOfferings = await $.ServiceOffering.list({
visibility: 'public',
})
// List featured offerings
const featured = await $.ServiceOffering.list({
featured: true,
visibility: 'public',
})find()
Find offerings matching specific criteria.
Signature:
$.ServiceOffering.find(query: OfferingQuery): Promise<ServiceOffering[]>Parameters:
query: Query object with filter criteria
Returns: Promise resolving to matching ServiceOfferings
Example:
// Find by category
const salesOfferings = await $.ServiceOffering.find({
category: 'sales',
visibility: 'public',
})
// Find by service
const serviceOfferings = await $.ServiceOffering.find({
service: 'service-id',
})
// Complex query with sorting
const topRated = await $.ServiceOffering.find({
visibility: 'public',
rating: { $gte: 4.5 },
})
.sort({ rating: -1 })
.limit(10)search()
Full-text search across offerings.
Signature:
$.ServiceOffering.search(query: string, options?: SearchOptions): Promise<ServiceOffering[]>Parameters:
query: Search query stringoptions: Optional search configuration
Returns: Promise resolving to matching ServiceOfferings
Example:
// Simple search
const results = await $.ServiceOffering.search('SDR outreach')
// Search with filters
const results = await $.ServiceOffering.search('content generation', {
category: 'marketing',
minRating: 4.0,
limit: 10,
})update()
Update offering properties.
Signature:
$.ServiceOffering[id].update(changes: Partial<OfferingConfig>): Promise<ServiceOffering>Parameters:
changes: Object containing properties to update
Returns: Promise resolving to updated ServiceOffering
Example:
// Update title and pricing
await $.ServiceOffering[offeringId].update({
title: 'Updated Title',
pricing: {
model: 'per-lead',
amount: 4.5,
currency: 'USD',
},
})
// Update visibility
await $.ServiceOffering[offeringId].update({
visibility: 'private',
})delete()
Delete an offering.
Signature:
$.ServiceOffering[id].delete(): Promise<void>Returns: Promise resolving when complete
Example:
await $.ServiceOffering[offeringId].delete()publish()
Publish an offering (set visibility to public).
Signature:
$.ServiceOffering[id].publish(): Promise<ServiceOffering>Returns: Promise resolving to updated ServiceOffering
Example:
await $.ServiceOffering[offeringId].publish()unpublish()
Unpublish an offering (set visibility to private).
Signature:
$.ServiceOffering[id].unpublish(): Promise<ServiceOffering>Returns: Promise resolving to updated ServiceOffering
Example:
await $.ServiceOffering[offeringId].unpublish()purchase()
Purchase an offering (creates order and initiates execution).
Signature:
$.ServiceOffering[id].purchase(config: PurchaseConfig): Promise<PurchaseResult>Parameters:
config: Purchase configuration
Returns: Promise resolving to purchase result
Example:
const purchase = await $.ServiceOffering[offeringId].purchase({
customer: $.User.current(),
params: {
leads: [{ name: 'John Doe', email: '[email protected]' }],
},
payment: {
method: 'card',
token: 'tok_visa_4242',
},
})
console.log(purchase.order)
console.log(purchase.execution)
console.log(purchase.payment)Property Access
ServiceOfferings support semantic property access:
// Get offering title
const title = await $.ServiceOffering[offeringId].title
// Get pricing
const pricing = await $.ServiceOffering[offeringId].pricing
// Get related service
const service = await $.ServiceOffering[offeringId].service
// Get computed metrics
const rating = await $.ServiceOffering[offeringId].rating
const reviewCount = await $.ServiceOffering[offeringId].reviewCount
const orderCount = await $.ServiceOffering[offeringId].orderCountRelations
service
Access the underlying service.
Pattern: $.ServiceOffering[id].service -> $.Service[serviceId]
Example:
const offering = await $.ServiceOffering.get('offering-123')
const service = await offering.service
console.log(service.workflow)orders
Access orders placed for this offering.
Pattern: $.ServiceOffering[id].orders -> $.ServiceOrder[]
Example:
const orders = await $.ServiceOffering[offeringId].orders
console.log(`Total orders: ${orders.length}`)reviews
Access customer reviews.
Pattern: $.ServiceOffering[id].reviews -> $.Review[]
Example:
const reviews = await $.ServiceOffering[offeringId].reviews
const avgRating = reviews.reduce((sum, r) => sum + r.rating, 0) / reviews.lengthprovider
Access the provider (inherited from service).
Pattern: $.ServiceOffering[id].provider -> $.Organization | $.Person
Example:
const provider = await $.ServiceOffering[offeringId].provider
console.log(provider.name)Usage Examples
Example 1: Create SDR Offering with Full Marketing
const sdrOffering = await $.ServiceOffering.create({
service: $.Service.get('sdr-service'),
title: 'AI-Powered SDR Outreach - Scale Your Pipeline',
description: 'Automated outreach that sounds human. Book more meetings without hiring.',
longDescription: `
# Scale Your Sales Pipeline with AI
Stop spending hours on manual outreach. Our AI-powered SDR service handles everything from lead research to personalized messaging.
## How It Works
1. **Upload your lead list** - CSV, CRM sync, or API integration
2. **AI researches each lead** - Company info, recent news, LinkedIn activity
3. **Personalized messages sent** - Via email and LinkedIn
4. **Responses routed to your team** - Real-time notifications
5. **Analytics dashboard tracks everything** - Open rates, response rates, meetings booked
## Results You Can Expect
- **10-15% average response rate** - 3x better than industry average
- **3-5% meeting booking rate** - Qualified meetings, not tire kickers
- **99% email deliverability** - Enterprise-grade infrastructure
- **24/7 automated follow-ups** - Never let a lead go cold
## What's Included
- Unlimited lead research
- Personalized email sequences
- LinkedIn connection requests
- Multi-channel follow-ups
- Real-time analytics
- CRM integration
- Dedicated support
## Perfect For
- B2B SaaS companies
- Sales teams of 5-50 reps
- Outbound-focused organizations
- Companies scaling their pipeline
`,
images: [
'https://cdn.services.do/sdr/hero.jpg',
'https://cdn.services.do/sdr/dashboard.png',
'https://cdn.services.do/sdr/analytics.png',
'https://cdn.services.do/sdr/messages.png',
],
featured: true,
visibility: 'public',
pricing: {
model: 'per-lead',
amount: 5,
currency: 'USD',
discount: {
type: 'volume',
tiers: [
{ min: 100, discount: 0.1 },
{ min: 500, discount: 0.2 },
{ min: 1000, discount: 0.3 },
],
},
},
category: 'sales',
tags: ['ai', 'sdr', 'outreach', 'b2b', 'automation'],
highlights: ['10x faster than manual outreach', '15% average response rate', '99% email deliverability', '24/7 AI monitoring', 'CRM integration included'],
benefits: [
'Save 20+ hours per week on prospecting',
'Generate 50% more pipeline',
'No hiring or training needed',
'Scale without adding headcount',
'Focus on closing, not cold calling',
],
features: [
'AI-powered personalization',
'Multi-channel outreach (email + LinkedIn)',
'Automated follow-up sequences',
'Real-time analytics dashboard',
'CRM integration (Salesforce, HubSpot)',
'A/B testing and optimization',
'Dedicated account manager',
'24/7 customer support',
],
testimonials: [
{
quote: 'This service 10x-ed our outbound pipeline in just 2 weeks. The personalization is incredible.',
author: 'Sarah Johnson',
title: 'VP Sales',
company: 'TechCorp Inc',
image: 'https://cdn.services.do/testimonials/sarah.jpg',
},
{
quote: 'We went from 2% to 12% response rate overnight. Game changer for our team.',
author: 'Mike Chen',
title: 'Head of Growth',
company: 'StartupXYZ',
},
],
callToAction: {
text: 'Start Free Trial',
action: 'start-trial',
},
restrictions: {
regions: ['US', 'CA', 'EU', 'UK'],
industries: ['B2B SaaS', 'Technology', 'Professional Services'],
minOrderSize: 10,
requiresApproval: false,
},
seo: {
metaTitle: 'AI SDR Outreach Service - Automate Your Sales Prospecting',
metaDescription: 'Automate your sales outreach with AI. 10x faster, 15% response rates, no hiring needed. Start your free trial today.',
keywords: ['ai sdr', 'sales automation', 'outreach service', 'lead generation', 'b2b sales'],
slug: 'ai-sdr-outreach-professional',
},
})Example 2: Create Content Writing Offering
const contentOffering = await $.ServiceOffering.create({
service: $.Service.get('content-service'),
title: 'AI Blog Post Writer - Professional Content at Scale',
description: 'High-quality blog posts written by AI, reviewed by humans. 10x your content output.',
images: ['https://cdn.services.do/content/hero.jpg'],
featured: false,
visibility: 'public',
pricing: {
model: 'per-unit',
amount: 50,
currency: 'USD',
discount: {
type: 'volume',
tiers: [
{ min: 10, discount: 0.15 },
{ min: 50, discount: 0.25 },
],
},
},
category: 'content',
tags: ['ai', 'content', 'blog', 'writing', 'seo'],
highlights: ['1000+ word blog posts', 'SEO optimized', 'Human review included', '24-hour turnaround', 'Unlimited revisions'],
benefits: ['10x your content production', 'Save 80% on content costs', 'Consistent brand voice', 'SEO-friendly content'],
features: [
'Topic research',
'Outline creation',
'Full blog post writing',
'Human editing and review',
'SEO optimization',
'Image suggestions',
'Meta descriptions',
'Internal linking',
],
callToAction: {
text: 'Order Your First Post',
action: 'order-now',
},
})Example 3: Query Featured Offerings
// Get all featured offerings
const featured = await $.ServiceOffering.find({
featured: true,
visibility: 'public',
})
console.log(`Found ${featured.length} featured offerings`)
featured.forEach((offering) => {
console.log(`${offering.title}: ${offering.rating} stars (${offering.reviewCount} reviews)`)
})Example 4: Sort Offerings by Popularity
// Get most popular offerings
const popular = await $.ServiceOffering.find({
visibility: 'public',
})
.sort({ orderCount: -1 })
.limit(10)
console.log('Top 10 Most Popular Services:')
popular.forEach((offering, index) => {
console.log(`${index + 1}. ${offering.title} (${offering.orderCount} orders)`)
})Example 5: Search Offerings by Keyword
// Search for AI automation services
const results = await $.ServiceOffering.search('ai automation workflow', {
category: 'automation',
minRating: 4.0,
limit: 20,
})
console.log(`Found ${results.length} matching services`)Example 6: Update Offering Pricing
// Update pricing with volume discount
await $.ServiceOffering[offeringId].update({
pricing: {
model: 'per-lead',
amount: 4.5,
currency: 'USD',
discount: {
type: 'volume',
tiers: [
{ min: 100, discount: 0.15 },
{ min: 500, discount: 0.25 },
{ min: 1000, discount: 0.35 },
],
},
},
})Example 7: Add Testimonial to Offering
// Add a new testimonial
const offering = await $.ServiceOffering.get('offering-id')
await $.ServiceOffering[offering.$id].update({
testimonials: [
...offering.testimonials,
{
quote: 'Absolutely transformed our content strategy. Highly recommended!',
author: 'Jane Smith',
title: 'Content Director',
company: 'MarketingCo',
},
],
})Example 8: Publish/Unpublish Offerings
// Publish an offering
await $.ServiceOffering[offeringId].publish()
console.log('Offering is now public')
// Unpublish temporarily
await $.ServiceOffering[offeringId].unpublish()
console.log('Offering is now private')Example 9: Create Private Enterprise Offering
const enterpriseOffering = await $.ServiceOffering.create({
service: $.Service.get('custom-ai-service'),
title: 'Enterprise AI Automation - Custom Solutions',
description: 'Custom AI automation solutions tailored for enterprise clients.',
visibility: 'private',
pricing: {
model: 'custom',
amount: 0,
currency: 'USD',
},
category: 'enterprise',
tags: ['enterprise', 'custom', 'ai', 'automation'],
restrictions: {
requiresApproval: true,
minOrderSize: 10000,
},
callToAction: {
text: 'Contact Sales',
action: 'contact-sales',
},
})Example 10: Get Offering Analytics
const offering = await $.ServiceOffering.get('offering-id')
// Get comprehensive analytics
const analytics = {
rating: offering.rating,
reviewCount: offering.reviewCount,
orderCount: offering.orderCount,
orders: await offering.orders,
reviews: await offering.reviews,
}
// Calculate conversion rate
const views = analytics.orderCount * 10 // Estimate: 1 order per 10 views
const conversionRate = (analytics.orderCount / views) * 100
console.log(`Analytics for ${offering.title}:`)
console.log(`- Rating: ${analytics.rating}/5 (${analytics.reviewCount} reviews)`)
console.log(`- Orders: ${analytics.orderCount}`)
console.log(`- Conversion Rate: ${conversionRate.toFixed(2)}%`)Example 11: Clone Offering for Different Market
const originalOffering = await $.ServiceOffering.get('original-offering-id')
// Create variation for enterprise market
const enterpriseOffering = await $.ServiceOffering.create({
...originalOffering,
title: `${originalOffering.title} - Enterprise`,
pricing: {
...originalOffering.pricing,
amount: originalOffering.pricing.amount * 3,
discount: {
type: 'volume',
tiers: [
{ min: 1000, discount: 0.2 },
{ min: 5000, discount: 0.3 },
],
},
},
features: [...originalOffering.features, 'Dedicated account manager', 'Custom SLA', 'Priority support', 'White-label option'],
})Example 12: Batch Update Featured Status
// Feature top-rated offerings
const topRated = await $.ServiceOffering.find({
visibility: 'public',
rating: { $gte: 4.8 },
})
await Promise.all(topRated.map((offering) => $.ServiceOffering[offering.$id].update({ featured: true })))
console.log(`Featured ${topRated.length} top-rated offerings`)Events
ServiceOfferings emit the following events:
offering.created- Offering was createdoffering.updated- Offering was updatedoffering.deleted- Offering was deletedoffering.published- Offering was publishedoffering.purchased- Offering was purchasedoffering.featured- Offering was featuredoffering.unfeatured- Offering was unfeatured
Example:
import { on } from 'sdk.do'
on.ServiceOffering.created(async (offering) => {
console.log(`New offering created: ${offering.title}`)
})
on.ServiceOffering.purchased(async ({ offering, order }) => {
console.log(`${offering.title} was purchased!`)
})API Endpoints
ServiceOfferings are accessible via REST API:
GET /api/offerings- List offerings (public)GET /api/offerings/:id- Get offering detailsPOST /api/offerings- Create offering (requires auth)PUT /api/offerings/:id- Update offering (requires auth)DELETE /api/offerings/:id- Delete offering (requires auth)POST /api/offerings/:id/purchase- Purchase offeringGET /api/offerings/featured- Get featured offeringsGET /api/offerings/category/:category- Get by categoryGET /api/offerings/search- Search offerings
Security
- Public Access: Anyone can view public offerings
- Private Access: Only authorized users can view private offerings
- Unlisted Access: Anyone with the direct link can view
- Modifications: Only service provider can modify
Schema.org Mapping
ServiceOfferings extend Schema.org types:
- schema.org/Offer: An offer to transfer some rights
- schema.org/Product: Any offered product or service
Property Mappings:
name->titledescription->descriptionimage->imagesoffers->pricingcategory->categoryaggregateRating->ratingandreviewCount
See Also
- Service API - Base service definition
- ServiceOrder API - Service orders
- ServiceExecution API - Execution tracking
- Pricing Types - Pricing models