Cleanflow API

A simple REST API to read and write deals and contacts, plus webhooks for real-time events. Used by integrations such as Zapier.

Base URL

https://www.1cleanflow.com/api/v1

Authentication

All requests require an API key. Create one in Cleanflow under Settings → Developer. Keys look like cf_… and are shown only once. Send the key as a bearer token:

Authorization: Bearer cf_your_api_key

Each key is scoped to one workspace. Requests without a valid key return 401.

Test connection

GET/api/v1/me

Returns the workspace the API key belongs to. Used to verify a key.

curl https://www.1cleanflow.com/api/v1/me \
  -H "Authorization: Bearer cf_your_api_key"

# 200
{ "workspace": { "id": "uuid", "name": "Acme Inc" } }

Deals

GET/api/v1/deals

Lists up to 50 deals, newest first. Optional since (ISO timestamp) returns only deals updated after that time — used for polling.

curl "https://www.1cleanflow.com/api/v1/deals?since=2026-01-01T00:00:00Z" \
  -H "Authorization: Bearer cf_your_api_key"

# 200
{ "data": [ { "id": "uuid", "title": "Acme – annual", "value": "5000", "currency": "USD", ... } ] }
POST/api/v1/deals

Creates a deal in the first pipeline/stage. Body: title (required), value, currency, personId, organizationId.

curl -X POST https://www.1cleanflow.com/api/v1/deals \
  -H "Authorization: Bearer cf_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Acme – annual", "value": 5000, "currency": "USD" }'

# 201
{ "data": { "id": "uuid", "title": "Acme – annual", ... } }
GET/api/v1/deals/:id

Fetch one deal with every field (including custom fields).

PATCH/api/v1/deals/:id

Update any field(s): title, value, currency, stageId, status (open|won|lost), expectedCloseDate, service, personId, organizationId, customFields. Only the keys you send change.

curl -X PATCH https://www.1cleanflow.com/api/v1/deals/DEAL_ID \
  -H "Authorization: Bearer cf_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "value": 7500, "status": "won", "customFields": { "FIELD_ID": "HVAC" } }'
DELETE/api/v1/deals/:id

Delete a deal.

Contacts (persons)

GET/api/v1/persons

Lists contacts, newest first. Optional since for polling.

curl https://www.1cleanflow.com/api/v1/persons \
  -H "Authorization: Bearer cf_your_api_key"

# 200
{ "data": [ { "id": "uuid", "name": "Jane Doe", "email": "jane@acme.com", ... } ] }
POST/api/v1/persons

Creates a contact. Body: name (required), email, phone, organizationId.

curl -X POST https://www.1cleanflow.com/api/v1/persons \
  -H "Authorization: Bearer cf_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Jane Doe", "email": "jane@acme.com" }'

# 201
{ "data": { "id": "uuid", "name": "Jane Doe", ... } }
GET/api/v1/persons/:id

Fetch one contact with every field (including custom fields).

PATCH/api/v1/persons/:id

Update any field(s): name, email, phone, address, organizationId, doNotCall, timezone, customFields.

curl -X PATCH https://www.1cleanflow.com/api/v1/persons/PERSON_ID \
  -H "Authorization: Bearer cf_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "address": "123 Main St", "customFields": { "FIELD_ID": "value" } }'
DELETE/api/v1/persons/:id

Delete a contact.

Custom fields

Custom fields you create in Settings → Data fields work over the API automatically — no code change. Set them with a customFields object keyed by field id, on create or update; values merge, and unknown keys are ignored. Discover field ids with:

GET/api/v1/fields?entity=deal|person

Lists custom-field definitions (id, name, type, options). Omit entity to get both.

curl "https://www.1cleanflow.com/api/v1/fields?entity=deal" \
  -H "Authorization: Bearer cf_your_api_key"

# 200
{ "data": [ { "id": "uuid", "name": "Service Required", "type": "select", "options": ["HVAC","Duct"] } ] }

Webhooks (REST hooks)

Subscribe a URL to an event; Cleanflow will POST to it when the event fires. This powers Zapier instant triggers. Supported events: deal.created, deal.won, person.created.

POST/api/v1/webhooks

Subscribe. Body: event and targetUrl. Returns the subscription id.

curl -X POST https://www.1cleanflow.com/api/v1/webhooks \
  -H "Authorization: Bearer cf_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "event": "deal.created", "targetUrl": "https://example.com/hook" }'

# 201
{ "id": "uuid" }
DELETE/api/v1/webhooks?id=<id>

Unsubscribe by subscription id.

curl -X DELETE "https://www.1cleanflow.com/api/v1/webhooks?id=uuid" \
  -H "Authorization: Bearer cf_your_api_key"

# 200
{ "ok": true }
GET/api/v1/webhooks

Lists your subscriptions and the available event names.

Delivered payloads have the shape:

{
  "event": "deal.created",
  "data": { "id": "uuid", "title": "Acme – annual", "value": "5000" },
  "ts": "2026-06-23T10:00:00.000Z"
}

Errors

Errors return a JSON body { "error": "message" } with an appropriate status: 400 (bad request), 401 (invalid/missing key).

Questions? Contact support at noreply@1cleanflow.com.