API Reference

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.

Privacy-First Architecture

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 Typessynced fields are accessible via API. device fields 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, or everyone.
  • 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
Keep Your API Key Secret

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.

synced Available via API
device On-device only — not accessible via API
Identity 15 fields
Canonical PathTypeStorageDescription
identity.first_nameStringsyncedFirst name
identity.middle_nameStringsyncedMiddle name
identity.last_nameStringsyncedLast name
identity.suffixStringsyncedSuffix (Jr, Sr, III)
identity.nicknameStringsyncedNickname
identity.preferred_nameStringsyncedPreferred name
identity.date_of_birthDatedeviceDate of birth
identity.genderStringsyncedGender
identity.pronounsStringsyncedPronouns
identity.ssnStringdeviceSocial Security Number
identity.itinStringdeviceIndividual Taxpayer ID
identity.citizenshipStringsyncedCitizenship
identity.primary_languageStringsyncedPrimary language
identity.languages_spoken[String]syncedLanguages spoken
identity.profile_photo_urlURLsyncedProfile photo URL
Contact 16 fields
Canonical PathTypeStorageDescription
contact.phone_primaryStringsyncedPrimary phone number
contact.phone_secondaryStringsyncedSecondary phone number
contact.phone_workStringsyncedWork phone number
contact.phone_typeStringsyncedPhone type (mobile, landline)
contact.sms_capableBoolsyncedWhether phone can receive SMS
contact.email_primaryStringsyncedPrimary email address
contact.email_secondaryStringsyncedSecondary email address
contact.email_workStringsyncedWork email address
contact.address_streetStringsyncedStreet address
contact.address_unitStringsyncedUnit / Apartment number
contact.address_cityStringsyncedCity
contact.address_stateStringsyncedState (2-letter code)
contact.address_zipStringsyncedZIP code
contact.address_countryStringsyncedCountry
contact.address_latDoublesyncedLatitude coordinate
contact.address_lngDoublesyncedLongitude coordinate
Social 14 fields
Canonical PathTypeStorageDescription
social.websiteURLsyncedPersonal website
social.instagramStringsyncedInstagram handle
social.facebookStringsyncedFacebook profile
social.tiktokStringsyncedTikTok handle
social.linkedinStringsyncedLinkedIn profile
social.x_twitterStringsyncedX / Twitter handle
social.youtubeStringsyncedYouTube channel
social.snapchatStringsyncedSnapchat handle
social.pinterestStringsyncedPinterest profile
social.redditStringsyncedReddit username
social.githubStringsyncedGitHub username
social.telegramStringsyncedTelegram handle
social.whatsappStringsyncedWhatsApp number
social.discordStringsyncedDiscord handle
Employment 14 fields
Canonical PathTypeStorageDescription
employment.statusStringsyncedEmployment status (employed, self, unemployed, retired, student)
employment.company_nameStringsyncedCompany name
employment.titleStringsyncedJob title
employment.industryStringsyncedIndustry
employment.start_dateDatesyncedEmployment start date
employment.work_typeStringsyncedWork type (w2, 1099, owner, gig)
employment.annual_incomeIntdeviceAnnual income
employment.hourly_rateIntdeviceHourly rate
employment.pay_frequencyStringdevicePay frequency (weekly, biweekly, monthly)
employment.skills[String]syncedSkills list
employment.certifications[String]syncedProfessional certifications
employment.licenses[String]syncedProfessional licenses
employment.years_experienceIntsyncedYears of experience
employment.service_categories[UUID]syncedService category IDs (FK to service_categories)
Financial 14 fields
Canonical PathTypeStorageDescription
financial.credit_scoreIntdeviceCredit score
financial.credit_score_sourceStringdeviceCredit score source
financial.credit_score_dateDatedeviceDate of credit score
financial.bank_nameStringdeviceBank name
financial.account_numberStringdeviceBank account number
financial.routing_numberStringdeviceBank routing number
financial.account_typeStringdeviceAccount type (checking, savings)
financial.stripe_customer_idStringsyncedStripe Customer ID
financial.stripe_connect_idStringsyncedStripe Connect account ID
financial.credit_balanceIntsyncedPlatform credit balance
financial.payout_enabledBoolsyncedWhether payouts are enabled
financial.tax_filing_statusStringdeviceTax filing status
financial.einStringdeviceEmployer Identification Number
financial.w9_on_fileBooldeviceW-9 form on file
Documents 16 fields
Canonical PathTypeStorageDescription
document.dl_numberStringdeviceDriver's license number
document.dl_stateStringdeviceLicense issuing state
document.dl_expiresDatedeviceLicense expiration date
document.dl_classStringdeviceLicense class
document.dl_imageFileRefdeviceEncrypted license image
document.passport_numberStringdevicePassport number
document.passport_countryStringdevicePassport issuing country
document.passport_expiresDatedevicePassport expiration date
document.utility_billFileRefdeviceScanned utility bill
document.pay_stubFileRefdeviceScanned pay stub
document.w2_formFileRefdeviceScanned W-2 form
document.ten99_formFileRefdeviceScanned 1099 form
document.insurance_cardFileRefdeviceScanned insurance card
document.proof_of_addressFileRefdeviceProof of address document
document.background_checkFileRefdeviceBackground check result
document.id_verifiedBoolsyncedWhether ID has been verified
Property 18 fields
Canonical PathTypeStorageDescription
property.ownership_statusStringsyncedOwnership status (own, rent, other)
property.property_typeStringsyncedProperty type (house, condo, apt, townhome, mobile)
property.year_builtIntsyncedYear built
property.sqftIntsyncedSquare footage
property.lot_sqftIntsyncedLot size in square feet
property.bedroomsIntsyncedNumber of bedrooms
property.bathroomsDoublesyncedNumber of bathrooms
property.storiesIntsyncedNumber of stories
property.garage_spacesIntsyncedGarage spaces
property.poolBoolsyncedHas pool
property.roof_typeStringsyncedRoof material type
property.roof_age_yearsIntsyncedRoof age in years
property.estimated_valueIntdeviceEstimated property value
property.mortgage_balanceIntdeviceRemaining mortgage balance
property.monthly_paymentIntdeviceMonthly mortgage payment
property.annual_taxIntdeviceAnnual property tax
property.utility_providerStringsyncedUtility provider name
property.monthly_electric_billIntdeviceMonthly electric bill amount
Vehicle 12 fields
Canonical PathTypeStorageDescription
vehicle.makeStringsyncedVehicle make
vehicle.modelStringsyncedVehicle model
vehicle.yearIntsyncedModel year
vehicle.colorStringsyncedVehicle color
vehicle.body_typeStringsyncedBody type (sedan, suv, truck, van, coupe)
vehicle.fuel_typeStringsyncedFuel type (gas, diesel, electric, hybrid)
vehicle.vinStringdeviceVehicle Identification Number
vehicle.license_plateStringdeviceLicense plate number
vehicle.plate_stateStringsyncedLicense plate state
vehicle.odometerIntsyncedCurrent odometer reading
vehicle.is_work_vehicleBoolsyncedUsed for work
vehicle.commercial_vehicleBoolsyncedCommercial vehicle registration
Insurance 16 fields
Canonical PathTypeStorageDescription
insurance.auto_carrierStringsyncedAuto insurance carrier
insurance.auto_policy_numberStringdeviceAuto policy number
insurance.auto_coverage_typeStringsyncedCoverage type (liability, full)
insurance.auto_expiresDatesyncedAuto policy expiration
insurance.home_carrierStringsyncedHome insurance carrier
insurance.home_policy_numberStringdeviceHome policy number
insurance.home_coverage_amountIntsyncedHome coverage amount
insurance.home_expiresDatesyncedHome policy expiration
insurance.health_carrierStringsyncedHealth insurance carrier
insurance.health_policy_numberStringdeviceHealth policy number
insurance.health_group_numberStringdeviceHealth group number
insurance.health_plan_typeStringsyncedHealth plan type (HMO, PPO, EPO, POS)
insurance.gl_carrierStringsyncedGeneral liability carrier
insurance.gl_policy_numberStringdeviceGL policy number
insurance.gl_coverage_amountIntsyncedGL coverage amount
insurance.gl_expiresDatesyncedGL policy expiration
Education 7 fields
Canonical PathTypeStorageDescription
education.highest_levelStringsyncedHighest education level (hs, associate, bachelor, master, doctorate, trade)
education.school_nameStringsyncedSchool name
education.degreeStringsyncedDegree name
education.field_of_studyStringsyncedField of study
education.graduation_yearIntsyncedGraduation year
education.trade_schoolStringsyncedTrade school name
education.apprenticeshipStringsyncedApprenticeship program
Health 10 fields
Canonical PathTypeStorageDescription
health.emergency_contact_nameStringsyncedEmergency contact name
health.emergency_contact_phoneStringsyncedEmergency contact phone
health.emergency_contact_relationStringsyncedRelationship to emergency contact
health.blood_typeStringdeviceBlood type
health.allergies[String]deviceKnown allergies
health.medications[String]deviceCurrent medications
health.medical_conditions[String]deviceMedical conditions
health.height_inchesIntsyncedHeight in inches
health.weight_lbsIntsyncedWeight in pounds
health.physical_limitations[String]syncedPhysical limitations
Household 8 fields
Canonical PathTypeStorageDescription
household.household_sizeIntsyncedNumber of household members
household.marital_statusStringsyncedMarital status
household.dependents_countIntsyncedNumber of dependents
household.pets[String]syncedPets in household
household.has_hoaBoolsyncedProperty in an HOA
household.move_in_dateDatesyncedMove-in date
household.household_incomeIntdeviceTotal household income
household.income_bracketStringsyncedIncome bracket (derived, not exact)
Preferences 10 fields
Canonical PathTypeStorageDescription
preference.contact_methodStringsyncedPreferred contact method (phone, text, email, app)
preference.contact_timeStringsyncedBest time to contact
preference.language_preferenceStringsyncedLanguage preference
preference.timezoneStringsyncedTimezone (IANA format)
preference.notifications_enabledBoolsyncedNotifications enabled
preference.marketing_opt_inBoolsyncedMarketing opt-in
preference.do_not_knockBoolsyncedDo not knock flag
preference.do_not_callBoolsyncedDo not call flag
preference.gate_codeStringsyncedGate code for property access
preference.access_notesStringsyncedAccess notes for service providers
Public Record 6 fields
Canonical PathTypeStorageDescription
publicRecord.voter_statusStringsyncedVoter registration status
publicRecord.voter_partyStringsyncedRegistered party affiliation
publicRecord.voter_registration_dateDatesyncedVoter registration date
publicRecord.voter_precinctStringsyncedVoter precinct
publicRecord.property_tax_assessedIntsyncedTax assessed property value
publicRecord.property_deed_dateDatesyncedProperty deed date
Platform 12 fields
Canonical PathTypeStorageDescription
platform.user_typeStringsyncedUser type (consumer, provider, both)
platform.subscription_tierStringsyncedSubscription tier (free, starter, pro, business, enterprise)
platform.onboarding_completeBoolsyncedWhether onboarding is complete
platform.vault_completenessDoublesyncedVault completeness score (0.0 to 1.0)
platform.trust_scoreDoublesyncedTrust score from verifications and activity
platform.average_ratingDoublesyncedAverage review rating
platform.total_reviewsIntsyncedTotal number of reviews
platform.total_bookingsIntsyncedTotal number of bookings
platform.total_knocksIntsyncedTotal canvassing knocks
platform.member_sinceDatesyncedPlatform join date
platform.referral_codeStringsyncedUnique referral code
platform.referred_byUUIDsyncedReferring 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.

GET /vault_data_points?contact_id=eq.{id}&category=eq.{category}

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.

ParameterTypeDescription
contact_id requiredUUIDContact UUID to read vault data for
category optionalStringFilter by category (identity, contact, social, etc.)
key optionalStringFilter by specific field key within category
select optionalStringColumns to return (default: all)
cURL
JavaScript
Python
# 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"
  }
]
POST /vault_data_points

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.

FieldTypeDescription
contact_id requiredUUIDContact UUID
category requiredStringCanonical category (e.g. "property")
key requiredStringCanonical field key (e.g. "roof_type")
value requiredStringField value (all values stored as text)
visibility optionalStringVisibility: hidden (default), contacts_only, everyone
source optionalStringData source: manual (default), scan, oauth, import, device
cURL
JavaScript
Python
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",
    },
)
PATCH /vault_data_points?contact_id=eq.{id}&category=eq.{cat}&key=eq.{key}

Update an existing vault data point by contact, category, and key. Only the fields you include in the body will be updated.

FieldTypeDescription
value optionalStringNew value
visibility optionalStringNew visibility setting
verified optionalBoolVerification status

Contacts

Manage contact records. Contacts are the core entity in the platform — every user, customer, and service provider is a contact.

GET /contacts?id=eq.{id}

Get a single contact by ID. Returns the full contact record including name, email, phone, and status.

ParameterTypeDescription
id requiredUUIDContact UUID
select optionalStringColumns to return
GET /contacts?or=(first_name.ilike.*{q}*,last_name.ilike.*{q}*,email.ilike.*{q}*)

Search contacts by name, email, or phone number using fuzzy matching. Combine with &deleted_at=is.null to exclude soft-deleted contacts.

ParameterTypeDescription
or requiredStringPostgREST OR filter with ilike matching across columns
limit optionalIntMax results (default: 20, max: 100)
order optionalStringSort order (e.g. created_at.desc)
cURL
JavaScript
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}`,
    },
  }
);
PATCH /contacts?id=eq.{id}

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.

FieldTypeDescription
first_name optionalStringFirst name
last_name optionalStringLast name
email optionalStringEmail address
phone optionalStringPhone number
display_name optionalStringDisplay name

Bookings

Create and manage service bookings. Bookings track the lifecycle of a service request from initial request through completion.

GET /bookings?business_id=eq.{id}

List bookings for a business, optionally filtered by status.

ParameterTypeDescription
business_id requiredUUIDBusiness UUID
status optionalStringFilter: requested, quoted, accepted, in_progress, completed, cancelled, disputed
limit optionalIntMax results (default: 20)
order optionalStringSort order
POST /bookings

Create a new booking / service request. Initially created with status requested.

FieldTypeDescription
customer_id requiredUUIDCustomer contact UUID
business_id requiredUUIDBusiness providing the service
listing_id optionalUUIDService listing UUID
scheduled_start optionalISO 8601Scheduled start datetime
scheduled_end optionalISO 8601Scheduled end datetime
notes optionalStringNotes for the booking
cURL
JavaScript
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",
    }),
  }
);
PATCH /bookings?id=eq.{id}

Update a booking's status and/or notes.

FieldTypeDescription
status optionalStringNew status: requested, quoted, accepted, in_progress, completed, cancelled, disputed
notes optionalStringUpdated notes
actual_start optionalISO 8601Actual start time
actual_end optionalISO 8601Actual end time
total_cents optionalIntTotal 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.

GET /platform_addresses?address_street=ilike.*{query}*

Search platform addresses by street, city, state, or ZIP. Returns matching addresses with property details and enrichment data.

ParameterTypeDescription
address_street requiredStringStreet address search (use ilike for fuzzy match)
address_city optionalStringCity filter
address_state optionalStringState filter (2-letter code)
address_zip optionalStringZIP code filter
limit optionalIntMax results (default: 20)
cURL
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 /platform_addresses?id=eq.{id}

Get full details for a specific address including all property data, enrichment fields, and linked contacts.

ParameterTypeDescription
id requiredUUIDAddress UUID
select optionalStringColumns 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.

POST /functions/v1/review-job-photos

Submit job photos for AI-powered quality review. Links to a booking and uses a review template to evaluate the submitted photos.

FieldTypeDescription
booking_id requiredUUIDBooking this review is for
template_id requiredStringReview template (e.g. "roof_inspection", "solar_install")
photo_urls required[String]Array of photo URLs to review
notes optionalStringAdditional notes
POST /functions/v1/scan-document

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.

FieldTypeDescription
image_url requiredStringURL of the document image
document_type requiredStringDocument type: drivers_license, insurance_card, utility_bill, pay_stub, w2
contact_id optionalUUIDContact 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_transactions?contact_id=eq.{id}

Get credit transaction history for a contact. Returns all credit transactions with amount, type, and business context.

ParameterTypeDescription
contact_id requiredUUIDContact UUID
order optionalStringSort order (e.g. created_at.desc)
limit optionalIntMax results
cURL
Python
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

Terminal
# 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

read_customer_vault
Read canonical vault fields for a customer. Returns values for each requested field path. Device-only fields (SSN, bank info, etc.) are blocked and return an error message.
write_customer_vault
Update synced vault fields for a customer. Accepts an object of canonical_path: value pairs. Automatically routes writes to the correct table (contacts, contact_profiles, or vault_data_points).
search_customers
Search contacts by name, email, or phone. Returns basic contact info for matching records. Uses fuzzy ilike matching across multiple columns.
create_booking
Create a new booking/service request. Requires customer_id and business_id. Optionally link to a listing and specify schedule.
update_booking
Update a booking's status and/or notes. Valid statuses: requested, quoted, accepted, in_progress, completed, cancelled, disputed.
list_bookings
List bookings for a business, optionally filtered by status. Returns recent bookings ordered by creation date.
search_addresses
Search platform addresses by street, city, state, or ZIP. Returns matching addresses with property and enrichment data from the 63M+ address database.
get_address_details
Get full details for a platform address including property data, resident info, voter data, and linked contacts.
submit_photo_review
Submit photos for AI review using a review template. Creates a review record linked to a booking with photo URLs for processing.
get_credit_balance
Check the credit balance for a contact. Returns the total balance across all businesses, plus per-business breakdown.

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:

JavaScript
Python
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

cURL
# 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

CodeMeaningDescription
200OKSuccessful GET, PATCH, DELETE request
201CreatedSuccessful POST request with resource creation
400Bad RequestInvalid parameters, malformed JSON, or missing required fields
401UnauthorizedMissing or invalid API key
403ForbiddenValid API key but insufficient permissions (RLS policy denial)
404Not FoundResource does not exist
409ConflictUnique constraint violation (e.g., duplicate vault data point)
429Too Many RequestsRate limit exceeded. Retry after the time in the Retry-After header.
500Internal Server ErrorServer error. Retry with exponential backoff.

Error Response Format

{
  "code": "PGRST204",
  "details": null,
  "hint": null,
  "message": "Column 'invalid_col' of relation 'contacts' does not exist"
}
PostgREST Error Codes

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.

Agentic Labs © 2025–2026