Marketplace API Documentation
The Agentic Labs Marketplace API provides programmatic access to the platform's personal data vault, contacts, bookings, address data, AI-powered photo reviews, and credit system. Built on Supabase PostgREST with 160+ canonical data fields across 15 categories.
Sensitive fields (SSN, bank accounts, medical data, financial details) are stored on-device only and are never accessible via the API. These fields are marked as device storage in the schema reference below.
Key Concepts
- Canonical Schema — 160+ standardized field names across 15 categories. Every data point maps to a single canonical path like
identity.first_name. - Storage Types —
syncedfields are accessible via API.devicefields stay on the user's phone and cannot be read or written remotely. - Visibility — Each synced field has a per-user visibility setting:
hidden,contacts_only, oreveryone. - Consent-Based Access — Business apps declare required fields. Users approve access per-field. API access is gated by consent.
Authentication
All API requests require an API key passed in two headers. The same key is used for both the apikey and Authorization headers.
Required Headers
apikey: your_api_key Authorization: Bearer your_api_key Content-Type: application/json
Your API key carries the same privileges as the user it belongs to. Do not expose it in client-side code, public repositories, or browser requests. Use it server-side only.
Base URL
https://ysegezedklvhfkwbttzv.supabase.co/rest/v1/
All endpoint paths in this documentation are relative to this base URL unless otherwise noted.
Edge Functions use https://ysegezedklvhfkwbttzv.supabase.co/functions/v1/ as their base.
Response Format
All responses are returned as JSON. Successful list queries return arrays. Single-object queries return arrays with one element. Use the Prefer: return=representation header on POST/PATCH to receive the created/updated object.
Canonical Schema Reference
The complete registry of 178 canonical fields organized across 15 categories. Every piece of user data in the platform maps to one of these canonical paths. Plugins, APIs, CSV imports, and business apps all use these keys as the universal data language.
| Canonical Path | Type | Storage | Description |
|---|---|---|---|
| identity.first_name | String | synced | First name |
| identity.middle_name | String | synced | Middle name |
| identity.last_name | String | synced | Last name |
| identity.suffix | String | synced | Suffix (Jr, Sr, III) |
| identity.nickname | String | synced | Nickname |
| identity.preferred_name | String | synced | Preferred name |
| identity.date_of_birth | Date | device | Date of birth |
| identity.gender | String | synced | Gender |
| identity.pronouns | String | synced | Pronouns |
| identity.ssn | String | device | Social Security Number |
| identity.itin | String | device | Individual Taxpayer ID |
| identity.citizenship | String | synced | Citizenship |
| identity.primary_language | String | synced | Primary language |
| identity.languages_spoken | [String] | synced | Languages spoken |
| identity.profile_photo_url | URL | synced | Profile photo URL |
| Canonical Path | Type | Storage | Description |
|---|---|---|---|
| contact.phone_primary | String | synced | Primary phone number |
| contact.phone_secondary | String | synced | Secondary phone number |
| contact.phone_work | String | synced | Work phone number |
| contact.phone_type | String | synced | Phone type (mobile, landline) |
| contact.sms_capable | Bool | synced | Whether phone can receive SMS |
| contact.email_primary | String | synced | Primary email address |
| contact.email_secondary | String | synced | Secondary email address |
| contact.email_work | String | synced | Work email address |
| contact.address_street | String | synced | Street address |
| contact.address_unit | String | synced | Unit / Apartment number |
| contact.address_city | String | synced | City |
| contact.address_state | String | synced | State (2-letter code) |
| contact.address_zip | String | synced | ZIP code |
| contact.address_country | String | synced | Country |
| contact.address_lat | Double | synced | Latitude coordinate |
| contact.address_lng | Double | synced | Longitude coordinate |
| Canonical Path | Type | Storage | Description |
|---|---|---|---|
| social.website | URL | synced | Personal website |
| social.instagram | String | synced | Instagram handle |
| social.facebook | String | synced | Facebook profile |
| social.tiktok | String | synced | TikTok handle |
| social.linkedin | String | synced | LinkedIn profile |
| social.x_twitter | String | synced | X / Twitter handle |
| social.youtube | String | synced | YouTube channel |
| social.snapchat | String | synced | Snapchat handle |
| social.pinterest | String | synced | Pinterest profile |
| social.reddit | String | synced | Reddit username |
| social.github | String | synced | GitHub username |
| social.telegram | String | synced | Telegram handle |
| social.whatsapp | String | synced | WhatsApp number |
| social.discord | String | synced | Discord handle |
| Canonical Path | Type | Storage | Description |
|---|---|---|---|
| employment.status | String | synced | Employment status (employed, self, unemployed, retired, student) |
| employment.company_name | String | synced | Company name |
| employment.title | String | synced | Job title |
| employment.industry | String | synced | Industry |
| employment.start_date | Date | synced | Employment start date |
| employment.work_type | String | synced | Work type (w2, 1099, owner, gig) |
| employment.annual_income | Int | device | Annual income |
| employment.hourly_rate | Int | device | Hourly rate |
| employment.pay_frequency | String | device | Pay frequency (weekly, biweekly, monthly) |
| employment.skills | [String] | synced | Skills list |
| employment.certifications | [String] | synced | Professional certifications |
| employment.licenses | [String] | synced | Professional licenses |
| employment.years_experience | Int | synced | Years of experience |
| employment.service_categories | [UUID] | synced | Service category IDs (FK to service_categories) |
| Canonical Path | Type | Storage | Description |
|---|---|---|---|
| financial.credit_score | Int | device | Credit score |
| financial.credit_score_source | String | device | Credit score source |
| financial.credit_score_date | Date | device | Date of credit score |
| financial.bank_name | String | device | Bank name |
| financial.account_number | String | device | Bank account number |
| financial.routing_number | String | device | Bank routing number |
| financial.account_type | String | device | Account type (checking, savings) |
| financial.stripe_customer_id | String | synced | Stripe Customer ID |
| financial.stripe_connect_id | String | synced | Stripe Connect account ID |
| financial.credit_balance | Int | synced | Platform credit balance |
| financial.payout_enabled | Bool | synced | Whether payouts are enabled |
| financial.tax_filing_status | String | device | Tax filing status |
| financial.ein | String | device | Employer Identification Number |
| financial.w9_on_file | Bool | device | W-9 form on file |
| Canonical Path | Type | Storage | Description |
|---|---|---|---|
| document.dl_number | String | device | Driver's license number |
| document.dl_state | String | device | License issuing state |
| document.dl_expires | Date | device | License expiration date |
| document.dl_class | String | device | License class |
| document.dl_image | FileRef | device | Encrypted license image |
| document.passport_number | String | device | Passport number |
| document.passport_country | String | device | Passport issuing country |
| document.passport_expires | Date | device | Passport expiration date |
| document.utility_bill | FileRef | device | Scanned utility bill |
| document.pay_stub | FileRef | device | Scanned pay stub |
| document.w2_form | FileRef | device | Scanned W-2 form |
| document.ten99_form | FileRef | device | Scanned 1099 form |
| document.insurance_card | FileRef | device | Scanned insurance card |
| document.proof_of_address | FileRef | device | Proof of address document |
| document.background_check | FileRef | device | Background check result |
| document.id_verified | Bool | synced | Whether ID has been verified |
| Canonical Path | Type | Storage | Description |
|---|---|---|---|
| property.ownership_status | String | synced | Ownership status (own, rent, other) |
| property.property_type | String | synced | Property type (house, condo, apt, townhome, mobile) |
| property.year_built | Int | synced | Year built |
| property.sqft | Int | synced | Square footage |
| property.lot_sqft | Int | synced | Lot size in square feet |
| property.bedrooms | Int | synced | Number of bedrooms |
| property.bathrooms | Double | synced | Number of bathrooms |
| property.stories | Int | synced | Number of stories |
| property.garage_spaces | Int | synced | Garage spaces |
| property.pool | Bool | synced | Has pool |
| property.roof_type | String | synced | Roof material type |
| property.roof_age_years | Int | synced | Roof age in years |
| property.estimated_value | Int | device | Estimated property value |
| property.mortgage_balance | Int | device | Remaining mortgage balance |
| property.monthly_payment | Int | device | Monthly mortgage payment |
| property.annual_tax | Int | device | Annual property tax |
| property.utility_provider | String | synced | Utility provider name |
| property.monthly_electric_bill | Int | device | Monthly electric bill amount |
| Canonical Path | Type | Storage | Description |
|---|---|---|---|
| vehicle.make | String | synced | Vehicle make |
| vehicle.model | String | synced | Vehicle model |
| vehicle.year | Int | synced | Model year |
| vehicle.color | String | synced | Vehicle color |
| vehicle.body_type | String | synced | Body type (sedan, suv, truck, van, coupe) |
| vehicle.fuel_type | String | synced | Fuel type (gas, diesel, electric, hybrid) |
| vehicle.vin | String | device | Vehicle Identification Number |
| vehicle.license_plate | String | device | License plate number |
| vehicle.plate_state | String | synced | License plate state |
| vehicle.odometer | Int | synced | Current odometer reading |
| vehicle.is_work_vehicle | Bool | synced | Used for work |
| vehicle.commercial_vehicle | Bool | synced | Commercial vehicle registration |
| Canonical Path | Type | Storage | Description |
|---|---|---|---|
| insurance.auto_carrier | String | synced | Auto insurance carrier |
| insurance.auto_policy_number | String | device | Auto policy number |
| insurance.auto_coverage_type | String | synced | Coverage type (liability, full) |
| insurance.auto_expires | Date | synced | Auto policy expiration |
| insurance.home_carrier | String | synced | Home insurance carrier |
| insurance.home_policy_number | String | device | Home policy number |
| insurance.home_coverage_amount | Int | synced | Home coverage amount |
| insurance.home_expires | Date | synced | Home policy expiration |
| insurance.health_carrier | String | synced | Health insurance carrier |
| insurance.health_policy_number | String | device | Health policy number |
| insurance.health_group_number | String | device | Health group number |
| insurance.health_plan_type | String | synced | Health plan type (HMO, PPO, EPO, POS) |
| insurance.gl_carrier | String | synced | General liability carrier |
| insurance.gl_policy_number | String | device | GL policy number |
| insurance.gl_coverage_amount | Int | synced | GL coverage amount |
| insurance.gl_expires | Date | synced | GL policy expiration |
| Canonical Path | Type | Storage | Description |
|---|---|---|---|
| education.highest_level | String | synced | Highest education level (hs, associate, bachelor, master, doctorate, trade) |
| education.school_name | String | synced | School name |
| education.degree | String | synced | Degree name |
| education.field_of_study | String | synced | Field of study |
| education.graduation_year | Int | synced | Graduation year |
| education.trade_school | String | synced | Trade school name |
| education.apprenticeship | String | synced | Apprenticeship program |
| Canonical Path | Type | Storage | Description |
|---|---|---|---|
| health.emergency_contact_name | String | synced | Emergency contact name |
| health.emergency_contact_phone | String | synced | Emergency contact phone |
| health.emergency_contact_relation | String | synced | Relationship to emergency contact |
| health.blood_type | String | device | Blood type |
| health.allergies | [String] | device | Known allergies |
| health.medications | [String] | device | Current medications |
| health.medical_conditions | [String] | device | Medical conditions |
| health.height_inches | Int | synced | Height in inches |
| health.weight_lbs | Int | synced | Weight in pounds |
| health.physical_limitations | [String] | synced | Physical limitations |
| Canonical Path | Type | Storage | Description |
|---|---|---|---|
| household.household_size | Int | synced | Number of household members |
| household.marital_status | String | synced | Marital status |
| household.dependents_count | Int | synced | Number of dependents |
| household.pets | [String] | synced | Pets in household |
| household.has_hoa | Bool | synced | Property in an HOA |
| household.move_in_date | Date | synced | Move-in date |
| household.household_income | Int | device | Total household income |
| household.income_bracket | String | synced | Income bracket (derived, not exact) |
| Canonical Path | Type | Storage | Description |
|---|---|---|---|
| preference.contact_method | String | synced | Preferred contact method (phone, text, email, app) |
| preference.contact_time | String | synced | Best time to contact |
| preference.language_preference | String | synced | Language preference |
| preference.timezone | String | synced | Timezone (IANA format) |
| preference.notifications_enabled | Bool | synced | Notifications enabled |
| preference.marketing_opt_in | Bool | synced | Marketing opt-in |
| preference.do_not_knock | Bool | synced | Do not knock flag |
| preference.do_not_call | Bool | synced | Do not call flag |
| preference.gate_code | String | synced | Gate code for property access |
| preference.access_notes | String | synced | Access notes for service providers |
| Canonical Path | Type | Storage | Description |
|---|---|---|---|
| publicRecord.voter_status | String | synced | Voter registration status |
| publicRecord.voter_party | String | synced | Registered party affiliation |
| publicRecord.voter_registration_date | Date | synced | Voter registration date |
| publicRecord.voter_precinct | String | synced | Voter precinct |
| publicRecord.property_tax_assessed | Int | synced | Tax assessed property value |
| publicRecord.property_deed_date | Date | synced | Property deed date |
| Canonical Path | Type | Storage | Description |
|---|---|---|---|
| platform.user_type | String | synced | User type (consumer, provider, both) |
| platform.subscription_tier | String | synced | Subscription tier (free, starter, pro, business, enterprise) |
| platform.onboarding_complete | Bool | synced | Whether onboarding is complete |
| platform.vault_completeness | Double | synced | Vault completeness score (0.0 to 1.0) |
| platform.trust_score | Double | synced | Trust score from verifications and activity |
| platform.average_rating | Double | synced | Average review rating |
| platform.total_reviews | Int | synced | Total number of reviews |
| platform.total_bookings | Int | synced | Total number of bookings |
| platform.total_knocks | Int | synced | Total canvassing knocks |
| platform.member_since | Date | synced | Platform join date |
| platform.referral_code | String | synced | Unique referral code |
| platform.referred_by | UUID | synced | Referring contact ID |
Vault Data
Read and write canonical vault fields for contacts. The vault resolves field paths to their correct storage location (contacts table, contact_profiles table, or vault_data_points table) automatically.
Read vault data points for a contact, optionally filtered by category. Returns all synced canonical fields stored in the vault. Device-only fields are never returned.
| Parameter | Type | Description |
|---|---|---|
| contact_id required | UUID | Contact UUID to read vault data for |
| category optional | String | Filter by category (identity, contact, social, etc.) |
| key optional | String | Filter by specific field key within category |
| select optional | String | Columns to return (default: all) |
# Read all identity fields for a contact curl "https://ysegezedklvhfkwbttzv.supabase.co/rest/v1/vault_data_points?contact_id=eq.a1b2c3d4-e5f6-7890-abcd-ef1234567890&category=eq.identity" \ -H "apikey: YOUR_API_KEY" \ -H "Authorization: Bearer YOUR_API_KEY"
const res = await fetch( `https://ysegezedklvhfkwbttzv.supabase.co/rest/v1/vault_data_points?contact_id=eq.${contactId}&category=eq.identity`, { headers: { "apikey": API_KEY, "Authorization": `Bearer ${API_KEY}`, }, } ); const data = await res.json();
import requests headers = { "apikey": API_KEY, "Authorization": f"Bearer {API_KEY}", } resp = requests.get( f"https://ysegezedklvhfkwbttzv.supabase.co/rest/v1/vault_data_points?contact_id=eq.{contact_id}&category=eq.identity", headers=headers, ) data = resp.json()
Response
[
{
"id": "uuid",
"contact_id": "a1b2c3d4-...",
"category": "identity",
"key": "first_name",
"value": "John",
"visibility": "contacts_only",
"verified": true,
"source": "scan",
"created_at": "2026-03-20T14:30:00Z",
"updated_at": "2026-03-20T14:30:00Z"
}
]
Write a new vault data point. Uses upsert semantics — if a record with the same contact_id + category + key already exists, it will be updated. Add the header Prefer: resolution=merge-duplicates for upsert behavior.
| Field | Type | Description |
|---|---|---|
| contact_id required | UUID | Contact UUID |
| category required | String | Canonical category (e.g. "property") |
| key required | String | Canonical field key (e.g. "roof_type") |
| value required | String | Field value (all values stored as text) |
| visibility optional | String | Visibility: hidden (default), contacts_only, everyone |
| source optional | String | Data source: manual (default), scan, oauth, import, device |
curl -X POST "https://ysegezedklvhfkwbttzv.supabase.co/rest/v1/vault_data_points" \ -H "apikey: YOUR_API_KEY" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -H "Prefer: resolution=merge-duplicates,return=representation" \ -d '{ "contact_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "category": "property", "key": "roof_type", "value": "composite shingle", "visibility": "contacts_only", "source": "import" }'
const res = await fetch( "https://ysegezedklvhfkwbttzv.supabase.co/rest/v1/vault_data_points", { method: "POST", headers: { "apikey": API_KEY, "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json", "Prefer": "resolution=merge-duplicates,return=representation", }, body: JSON.stringify({ contact_id: contactId, category: "property", key: "roof_type", value: "composite shingle", visibility: "contacts_only", source: "import", }), } );
resp = requests.post( "https://ysegezedklvhfkwbttzv.supabase.co/rest/v1/vault_data_points", headers={ "apikey": API_KEY, "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", "Prefer": "resolution=merge-duplicates,return=representation", }, json={ "contact_id": contact_id, "category": "property", "key": "roof_type", "value": "composite shingle", "visibility": "contacts_only", "source": "import", }, )
Update an existing vault data point by contact, category, and key. Only the fields you include in the body will be updated.
| Field | Type | Description |
|---|---|---|
| value optional | String | New value |
| visibility optional | String | New visibility setting |
| verified optional | Bool | Verification status |
Contacts
Manage contact records. Contacts are the core entity in the platform — every user, customer, and service provider is a contact.
Get a single contact by ID. Returns the full contact record including name, email, phone, and status.
| Parameter | Type | Description |
|---|---|---|
| id required | UUID | Contact UUID |
| select optional | String | Columns to return |
Search contacts by name, email, or phone number using fuzzy matching. Combine with &deleted_at=is.null to exclude soft-deleted contacts.
| Parameter | Type | Description |
|---|---|---|
| or required | String | PostgREST OR filter with ilike matching across columns |
| limit optional | Int | Max results (default: 20, max: 100) |
| order optional | String | Sort order (e.g. created_at.desc) |
curl "https://ysegezedklvhfkwbttzv.supabase.co/rest/v1/contacts?or=(first_name.ilike.*john*,last_name.ilike.*john*,email.ilike.*john*)&deleted_at=is.null&limit=20&order=created_at.desc" \ -H "apikey: YOUR_API_KEY" \ -H "Authorization: Bearer YOUR_API_KEY"
const q = "john"; const res = await fetch( `https://ysegezedklvhfkwbttzv.supabase.co/rest/v1/contacts?or=(first_name.ilike.*${q}*,last_name.ilike.*${q}*,email.ilike.*${q}*)&deleted_at=is.null&limit=20`, { headers: { "apikey": API_KEY, "Authorization": `Bearer ${API_KEY}`, }, } );
Update a contact record. Only the fields you include in the body will be updated. Some canonical fields (like identity.first_name) map directly to contacts table columns.
| Field | Type | Description |
|---|---|---|
| first_name optional | String | First name |
| last_name optional | String | Last name |
| email optional | String | Email address |
| phone optional | String | Phone number |
| display_name optional | String | Display name |
Bookings
Create and manage service bookings. Bookings track the lifecycle of a service request from initial request through completion.
List bookings for a business, optionally filtered by status.
| Parameter | Type | Description |
|---|---|---|
| business_id required | UUID | Business UUID |
| status optional | String | Filter: requested, quoted, accepted, in_progress, completed, cancelled, disputed |
| limit optional | Int | Max results (default: 20) |
| order optional | String | Sort order |
Create a new booking / service request. Initially created with status requested.
| Field | Type | Description |
|---|---|---|
| customer_id required | UUID | Customer contact UUID |
| business_id required | UUID | Business providing the service |
| listing_id optional | UUID | Service listing UUID |
| scheduled_start optional | ISO 8601 | Scheduled start datetime |
| scheduled_end optional | ISO 8601 | Scheduled end datetime |
| notes optional | String | Notes for the booking |
curl -X POST "https://ysegezedklvhfkwbttzv.supabase.co/rest/v1/bookings" \ -H "apikey: YOUR_API_KEY" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -H "Prefer: return=representation" \ -d '{ "customer_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "business_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "scheduled_start": "2026-04-15T09:00:00Z", "notes": "Replace water heater" }'
const res = await fetch( "https://ysegezedklvhfkwbttzv.supabase.co/rest/v1/bookings", { method: "POST", headers: { "apikey": API_KEY, "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json", "Prefer": "return=representation", }, body: JSON.stringify({ customer_id: "a1b2c3d4-...", business_id: "b2c3d4e5-...", scheduled_start: "2026-04-15T09:00:00Z", notes: "Replace water heater", }), } );
Update a booking's status and/or notes.
| Field | Type | Description |
|---|---|---|
| status optional | String | New status: requested, quoted, accepted, in_progress, completed, cancelled, disputed |
| notes optional | String | Updated notes |
| actual_start optional | ISO 8601 | Actual start time |
| actual_end optional | ISO 8601 | Actual end time |
| total_cents optional | Int | Total amount in cents |
Addresses
Search and query the platform's nationwide address database with 63M+ indexed addresses, enriched with property data, voter records, and more.
Search platform addresses by street, city, state, or ZIP. Returns matching addresses with property details and enrichment data.
| Parameter | Type | Description |
|---|---|---|
| address_street required | String | Street address search (use ilike for fuzzy match) |
| address_city optional | String | City filter |
| address_state optional | String | State filter (2-letter code) |
| address_zip optional | String | ZIP code filter |
| limit optional | Int | Max results (default: 20) |
curl "https://ysegezedklvhfkwbttzv.supabase.co/rest/v1/platform_addresses?address_street=ilike.*Oak*&address_state=eq.TX&limit=10&select=id,address_street,address_city,address_state,address_zip,sqft,bedrooms,bathrooms,roof_type" \ -H "apikey: YOUR_API_KEY" \ -H "Authorization: Bearer YOUR_API_KEY"
Get full details for a specific address including all property data, enrichment fields, and linked contacts.
| Parameter | Type | Description |
|---|---|---|
| id required | UUID | Address UUID |
| select optional | String | Columns to return (use * for all) |
Response Fields Include
id, address_street, address_city, address_state, address_zip, lat, lng, property_type, year_built, sqft, lot_sqft, assessed_value, owner_name, bedrooms, bathrooms, stories, pool, roof_type, do_not_knock, is_renter, voter_status, voter_party
Edge Functions
Serverless functions for AI-powered features like photo review and document scanning.
Submit job photos for AI-powered quality review. Links to a booking and uses a review template to evaluate the submitted photos.
| Field | Type | Description |
|---|---|---|
| booking_id required | UUID | Booking this review is for |
| template_id required | String | Review template (e.g. "roof_inspection", "solar_install") |
| photo_urls required | [String] | Array of photo URLs to review |
| notes optional | String | Additional notes |
Submit a document image for AI-powered data extraction. The function uses Gemini Vision to extract structured data and map it to canonical vault fields.
| Field | Type | Description |
|---|---|---|
| image_url required | String | URL of the document image |
| document_type required | String | Document type: drivers_license, insurance_card, utility_bill, pay_stub, w2 |
| contact_id optional | UUID | Contact to auto-fill fields for |
Response
{
"extracted_fields": {
"identity.first_name": "John",
"identity.last_name": "Smith",
"contact.address_street": "3231 Running Fawn Dr",
"document.dl_number": "[REDACTED]",
"document.dl_expires": "2028-11-15"
},
"confidence": 0.95,
"document_type": "drivers_license"
}
Credits
Query platform credit balances and transaction history. Credits power the platform economy for referrals, canvassing rewards, and business incentives.
Get credit transaction history for a contact. Returns all credit transactions with amount, type, and business context.
| Parameter | Type | Description |
|---|---|---|
| contact_id required | UUID | Contact UUID |
| order optional | String | Sort order (e.g. created_at.desc) |
| limit optional | Int | Max results |
curl "https://ysegezedklvhfkwbttzv.supabase.co/rest/v1/credit_transactions?contact_id=eq.a1b2c3d4-e5f6-7890-abcd-ef1234567890&order=created_at.desc&limit=50" \ -H "apikey: YOUR_API_KEY" \ -H "Authorization: Bearer YOUR_API_KEY"
resp = requests.get( f"https://ysegezedklvhfkwbttzv.supabase.co/rest/v1/credit_transactions", headers=headers, params={ "contact_id": f"eq.{contact_id}", "order": "created_at.desc", "limit": "50", }, )
MCP Server
The Marketplace MCP server enables AI assistants and external tools to interact with the platform via the Model Context Protocol. Connect your AI assistant, IDE, or automation tool for 2-way data sync.
Installation
# Clone and install git clone https://github.com/agntc-labs/marketplace.git cd marketplace/mcp-server npm install # Set environment variables export SUPABASE_URL="https://ysegezedklvhfkwbttzv.supabase.co" export SUPABASE_SERVICE_KEY="your_service_role_key" # Run the server node index.js
Claude Desktop Configuration
Add this to your claude_desktop_config.json:
{
"mcpServers": {
"marketplace": {
"command": "node",
"args": ["/path/to/marketplace/mcp-server/index.js"],
"env": {
"SUPABASE_URL": "https://ysegezedklvhfkwbttzv.supabase.co",
"SUPABASE_SERVICE_KEY": "your_service_role_key"
}
}
}
}
Available Tools
Code Examples
Complete working examples for common API workflows.
Read Customer Profile (Multi-Source)
This pattern reads data from both the contacts table and vault_data_points in a single workflow:
const BASE = "https://ysegezedklvhfkwbttzv.supabase.co/rest/v1"; const headers = { "apikey": API_KEY, "Authorization": `Bearer ${API_KEY}`, }; async function getFullProfile(contactId) { // Fetch contact + vault data in parallel const [contact, vault] = await Promise.all([ fetch(`${BASE}/contacts?id=eq.${contactId}&select=*`, { headers }) .then(r => r.json()), fetch(`${BASE}/vault_data_points?contact_id=eq.${contactId}`, { headers }) .then(r => r.json()), ]); // Merge into a unified profile const profile = { ...contact[0] }; for (const point of vault) { profile[`${point.category}.${point.key}`] = point.value; } return profile; }
import requests from concurrent.futures import ThreadPoolExecutor BASE = "https://ysegezedklvhfkwbttzv.supabase.co/rest/v1" headers = { "apikey": API_KEY, "Authorization": f"Bearer {API_KEY}", } def get_full_profile(contact_id: str) -> dict: with ThreadPoolExecutor() as executor: contact_fut = executor.submit( requests.get, f"{BASE}/contacts?id=eq.{contact_id}&select=*", headers=headers, ) vault_fut = executor.submit( requests.get, f"{BASE}/vault_data_points?contact_id=eq.{contact_id}", headers=headers, ) contact = contact_fut.result().json()[0] vault = vault_fut.result().json() profile = {**contact} for point in vault: profile[f"{point['category']}.{point['key']}"] = point["value"] return profile
Batch Update Vault Fields
# Update multiple property fields in a single request # Note: PostgREST supports bulk insert with arrays curl -X POST "https://ysegezedklvhfkwbttzv.supabase.co/rest/v1/vault_data_points" \ -H "apikey: YOUR_API_KEY" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -H "Prefer: resolution=merge-duplicates,return=representation" \ -d '[ {"contact_id":"a1b2...","category":"property","key":"roof_type","value":"composite","source":"import"}, {"contact_id":"a1b2...","category":"property","key":"roof_age_years","value":"3","source":"import"}, {"contact_id":"a1b2...","category":"property","key":"sqft","value":"2400","source":"import"}, {"contact_id":"a1b2...","category":"property","key":"bedrooms","value":"4","source":"import"} ]'
Rate Limits & Errors
API rate limits and standard error response format.
Rate Limits
Free tier: 500 requests/minute, 50,000 requests/day
Pro tier: 2,000 requests/minute, 500,000 requests/day
Enterprise: Custom limits. Contact us.
HTTP Status Codes
| Code | Meaning | Description |
|---|---|---|
| 200 | OK | Successful GET, PATCH, DELETE request |
| 201 | Created | Successful POST request with resource creation |
| 400 | Bad Request | Invalid parameters, malformed JSON, or missing required fields |
| 401 | Unauthorized | Missing or invalid API key |
| 403 | Forbidden | Valid API key but insufficient permissions (RLS policy denial) |
| 404 | Not Found | Resource does not exist |
| 409 | Conflict | Unique constraint violation (e.g., duplicate vault data point) |
| 429 | Too Many Requests | Rate limit exceeded. Retry after the time in the Retry-After header. |
| 500 | Internal Server Error | Server error. Retry with exponential backoff. |
Error Response Format
{
"code": "PGRST204",
"details": null,
"hint": null,
"message": "Column 'invalid_col' of relation 'contacts' does not exist"
}
The API is powered by PostgREST. Error codes starting with PGRST are PostgREST-specific. Codes starting with numbers (e.g., 23505) are PostgreSQL constraint violations. See the PostgREST error reference for details.