How to upload
- Sign in to your JobStak client portal.
- Go to CL Listings → Import XML/CSV.
- Choose a
.xml file and click Upload & Process.
- Each
<listing> is validated independently. Valid listings are added; invalid rows are skipped with a per-row reason.
Document structure
- Root element:
<listings>.
- One
<listing> child per posting record.
description_html should be wrapped in <![CDATA[ ... ]]> to preserve HTML markup.
city_markets contains one or more <city> children — one per Craigslist city slug.
- Encoding must be
UTF-8. Reserved characters outside CDATA must be escaped.
Common fields (all listing types)
| Field | Required | Type | Notes |
external_reference_id | Recommended | string | Your unique ID. Used for deduplication on re-upload. |
listing_type | Required | enum | service | real_estate_rent | real_estate_sale |
title | Required | string (5–70) | Plain text. Avoid ALL CAPS and emoji-spam. |
description_html | Required | HTML / text | Wrap in CDATA. ≥ 20 chars of visible text after stripping tags. |
city | Required | string | Physical city of the listing. |
state_region | Required | string | State or region code. |
contact_email | One required | email | Either contact_email or contact_phone. |
contact_phone | One required | string | E.164 or local format. |
canonical_url | Optional | URL | Must be valid http(s) when present. |
city_markets | Required | list | Repeat one <city> child per Craigslist slug. |
Service fields
Required when listing_type = service.
| Field | Required | Notes |
service_type | Required | e.g. cleaning, moving, lessons, handyman. |
price_type | Required | fixed | hourly | starting_at | quote_required |
price_min | Conditional | Required unless price_type = quote_required. |
price_max | Optional | ≥ price_min if provided. |
service_area_mode | Optional | onsite | remote | mobile | hybrid |
service_radius_miles | Optional | Cannot be set when service_area_mode = remote. |
business_name | Optional | Shown in posting body. |
Real estate fields
Required when listing_type = real_estate_rent or real_estate_sale.
| Field | Required | Notes |
listing_intent | Required | Must be rent or sale matching listing_type. |
property_type | Required | apartment, house, condo, townhouse, room, etc. |
price | Required | > 0 USD. |
deposit | Optional | ≥ 0 (rentals). |
sqft | Optional | Integer. |
bedrooms | Optional | 0 = studio. |
bathrooms | Optional | Allows 0.5 increments. |
available_date | Optional | YYYY-MM-DD. |
pets_allowed | Optional | yes / no. |
furnished | Optional | yes / no. |
Validation rules
- Title: 5–70 characters.
- Description: ≥ 20 chars of visible text after HTML is stripped.
- Contact: at least one of
contact_email or contact_phone.
- Service price:
price_min required unless price_type = quote_required; price_max ≥ price_min.
- Real estate price: > 0;
deposit not negative.
- listing_intent must match
listing_type.
- Deduplication: repeat
external_reference_id values are skipped.
Full XML example
<?xml version="1.0" encoding="UTF-8"?>
<listings>
<listing>
<external_reference_id>SVC-001</external_reference_id>
<listing_type>service</listing_type>
<title>Eco-Friendly House Cleaning</title>
<description_html><![CDATA[<p>Weekly or one-time cleaning with non-toxic products.</p>]]></description_html>
<city>Austin</city>
<state_region>TX</state_region>
<contact_email>hello@example.com</contact_email>
<service_type>cleaning</service_type>
<price_type>hourly</price_type>
<price_min>45</price_min>
<price_max>75</price_max>
<city_markets>
<city>austin</city>
<city>sanantonio</city>
</city_markets>
</listing>
</listings>
Programmatic upload
curl -X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "file=@listings.xml" \
https://ipuanzeiogwtxvberefu.supabase.co/functions/v1/upload-listings-feed