Build modular workflows on top of Vynflow using service-account authenticated JSON APIs. Today's public surfaces are the Vynflow AI schema-driven AI endpoint and the User Tables row CRUD API.
All requests require the following headers:
Authorization: Bearer sa-p-vynflow-SECRET
X-API-Key: sa-k-vynflow-KEY
X-Domain-ID: DOMAIN_UUID
One schema-driven AI endpoint. Describe the fields you want back, send a prompt (and optional named data), and Vynflow AI routes the request to the cheapest model that can do the job — breaking it into subtasks when needed — then returns a JSON object shaped exactly like your requested fields. Token usage, cost and routing are recorded in your domain's Vynflow AI history.
POST https://vynflow.cloud/api/ai/complete
Request and response:
curl -X POST https://vynflow.cloud/api/ai/complete \
-H "Authorization: Bearer sa-p-vynflow-SECRET" \
-H "X-API-Key: sa-k-vynflow-KEY" \
-H "X-Domain-ID: DOMAIN_UUID" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Summarise the feedback and classify its sentiment.",
"response_fields": [
{ "name": "summary", "type": "string", "required": true },
{ "name": "sentiment", "type": "enum", "required": true, "options": ["positive","neutral","negative"] }
],
"data": [
{ "name": "feedback", "value": "The app is fast but it crashed twice today." }
]
}'
# → { "result": { "summary": "...", "sentiment": "negative" },
# "routing": { "tier": "standard", "decomposed": false },
# "usage": { "total_tokens": 448, "cost_usd": "$0.000180" } }
Each response_fields entry is { name, type, required } with optional
description, options (for enum) and items (for
array). Supported field types: string, number,
integer, boolean, array, object, enum.
Non-required fields may return null.
Table discovery and schema:
POST https://vynflow.cloud/api/user-tables
GET https://vynflow.cloud/api/user-tables
GET https://vynflow.cloud/api/user-tables/{TABLE_ID}/schema
Row CRUD:
POST https://vynflow.cloud/api/user-tables/{TABLE_ID}/rows
POST https://vynflow.cloud/api/user-tables/{TABLE_ID}/rows/from-columns
GET https://vynflow.cloud/api/user-tables/{TABLE_ID}/rows
GET https://vynflow.cloud/api/user-tables/{TABLE_ID}/row/{ROW_ID}
PUT https://vynflow.cloud/api/user-tables/{TABLE_ID}/row/{ROW_ID}
PATCH https://vynflow.cloud/api/user-tables/{TABLE_ID}/row/{ROW_ID}
DELETE https://vynflow.cloud/api/user-tables/{TABLE_ID}/row/{ROW_ID}
Batch row writes (up to 1,000 items per request, partial success → HTTP 207 on any failure):
POST https://vynflow.cloud/api/user-tables/{TABLE_ID}/rows/batch
POST https://vynflow.cloud/api/user-tables/{TABLE_ID}/rows/batch-update
POST https://vynflow.cloud/api/user-tables/{TABLE_ID}/rows/upsert
POST https://vynflow.cloud/api/user-tables/{TABLE_ID}/rows/batch-delete
File upload:
POST https://vynflow.cloud/api/user-tables/{TABLE_ID}/attachment/upload
An attachment column holds a file. The bytes live in object storage and the row keeps the file’s ID.
A single attachment can be up to 64 MB. There are two ways to send one.
Upload the bytes, then reference the ID. Best for large files — the body is sent as-is, with no
base64 inflation. Name the file with X-File-Name (or a Content-Disposition filename, or
?file_name=) and type it with Content-Type; omit the type and it is detected from the file’s
magic bytes.
curl -X POST https://vynflow.cloud/api/user-tables/TABLE_ID/attachment/upload \
-H "Authorization: Bearer sa-p-vynflow-SECRET" \
-H "X-API-Key: sa-k-vynflow-KEY" \
-H "X-Domain-ID: DOMAIN_UUID" \
-H "Content-Type: application/pdf" \
-H "X-File-Name: invoice.pdf" \
--data-binary @invoice.pdf
# → { "id": "FILE_UUID", "file_name": "invoice.pdf", "size_bytes": 48213904 }
Then use that id as the column value on any row write. The endpoint also accepts
multipart/form-data with a file part.
Or send the file inline with the row. Every JSON row-write endpoint accepts file content directly in an attachment column — Vynflow stores it and substitutes the file ID before writing the row, so one request is enough.
curl -X POST https://vynflow.cloud/api/user-tables/TABLE_ID/rows \
-H "Authorization: Bearer sa-p-vynflow-SECRET" \
-H "X-API-Key: sa-k-vynflow-KEY" \
-H "X-Domain-ID: DOMAIN_UUID" \
-H "Content-Type: application/json" \
-d '{
"data": {
"Name": "Acme",
"Invoice": {
"file_name": "invoice.pdf",
"content_type": "application/pdf",
"content_base64": "JVBERi0xLjcKJc..."
}
}
}'
An attachment value can be an existing file ID, a data URL
(data:application/pdf;base64,...), an object with content_base64, an object with a
bytes array, a bare byte array, or null to clear the cell. Base64 is decoded leniently —
standard or URL-safe alphabet, padding optional, line breaks ignored.
Create a table:
curl -X POST https://vynflow.cloud/api/user-tables \
-H "Authorization: Bearer sa-p-vynflow-SECRET" \
-H "X-API-Key: sa-k-vynflow-KEY" \
-H "X-Domain-ID: DOMAIN_UUID" \
-H "Content-Type: application/json" \
-d '{
"name": "Vendors",
"description": "All vendors and key contacts"
}'
Get schema for a table:
curl -X GET https://vynflow.cloud/api/user-tables/TABLE_ID/schema \
-H "Authorization: Bearer sa-p-vynflow-SECRET" \
-H "X-API-Key: sa-k-vynflow-KEY" \
-H "X-Domain-ID: DOMAIN_UUID"
Create a row:
curl -X POST https://vynflow.cloud/api/user-tables/TABLE_ID/rows \
-H "Authorization: Bearer sa-p-vynflow-SECRET" \
-H "X-API-Key: sa-k-vynflow-KEY" \
-H "X-Domain-ID: DOMAIN_UUID" \
-H "Content-Type: application/json" \
-d '{
"data": {
"Name": "Acme",
"Amount": 1200,
"Active": true
}
}'
List rows (with filtering/sorting):
curl -X GET "https://vynflow.cloud/api/user-tables/TABLE_ID/rows?page=1&per_page=10&filter_col=Name&filter_value=Acme&sort_col=CreatedAt&sort_dir=desc" \
-H "Authorization: Bearer sa-p-vynflow-SECRET" \
-H "X-API-Key: sa-k-vynflow-KEY" \
-H "X-Domain-ID: DOMAIN_UUID"