Skip to the page

Developers

Connect Arqiflow to the rest of your tools.

A REST API over a firm's projects, stages, tasks, people, time, files and comments, webhooks for what happens to them, and apps for Zapier and Make.

Getting started

An owner or a manager creates an API key in Settings › Integrations › API and webhooks. The key is shown once. It acts for the person who made it, with exactly what they may see and do, and what it changes is recorded as theirs, “via” the key's name.

Send it as a bearer token to your firm's Arqiflow address:

curl https://app.arqiflow.com/v1/tasks?status=to_approve \
  -H "Authorization: Bearer arqk_..."

Add a task to the stage a project is in now:

curl https://app.arqiflow.com/v1/tasks \
  -H "Authorization: Bearer arqk_..." \
  -H "Content-Type: application/json" \
  -d '{"project_id": "prj_8c1d2e3f4a", "title": "Ground floor plan",
       "due_on": "2026-11-06", "fields": {"Sheet number": "A-101"}}'

Conventions

  • JSON in and out. Times are ISO 8601 with their zone, days are YYYY-MM-DD.
  • Lists are newest first: {"data": [...], "has_more": true, "next_cursor": "..."}. Pass cursor for the next page and limit (1 to 100, 50 by default) for its size.created_since and updated_since are for polling.
  • Errors are {"error": {"type": "...", "message": "..."}} with 400, 401, 402 (the firm's plan has ended, so it only reads), 403, 404 or 429.
  • 120 requests a minute a key. Every answer carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; a 429 carries Retry-After.
  • The rules are the app's: a guest only reads, approving is for the task's reviewer or a lead, sending back needs a reason. What looks out of order comes back as warnings, and is done.
  • /v1 only grows. Anything that would remove or rename becomes /v2.

Resources

MethodPathWhat
GET/v1/meThe key, the person it acts for, and the firm
GET POST/v1/projectsProjects; q, status, archived, created_since
GET PATCH/v1/projects/{id}A project: name, client, number, status, colour
GET/v1/projects/{id}/stagesA project's stages, in order
GET/v1/stages/{id}A stage, with when it was signed off
GET POST/v1/tasksTasks; project_id, stage_id, status, assignee_id, q, updated_since
GET PATCH/v1/tasks/{id}A task, with the firm's own fields by name
POST/v1/tasks/{id}/actions/{action}start, submit, approve, send_back, reopen, drop
GET POST/v1/tasks/{id}/commentsA task's comments
GET/v1/commentsComments on every task the key may see
GET/v1/peopleThe firm's people; email, q
GET POST/v1/time-entriesTime; user_id, project_id, task_id, from, to
GET/v1/filesFiles' details on tasks and projects
GET/v1/form-responsesResponses to a project's forms
GET POST DELETE/v1/hooksSubscribe an address to an event, and unsubscribe
GET/v1/eventsThe webhook events, each with a sample

A task looks like this, and a webhook sends the same:

{
  "id": "wrk_3f9a1c2b7d", "project_id": "prj_8c1d2e3f4a", "stage_id": "stg_1a2b3c4d5e",
  "title": "Ground floor plan", "status": "to_approve", "discipline": "Architecture",
  "assignee": {"id": "…", "name": "Bana Saleh", "email": "[email protected]"},
  "reviewer": null, "starts_on": "2026-11-02", "due_on": "2026-11-06", "estimate_hours": 16,
  "fields": {"Sheet number": "A-101"},
  "created_at": "2026-10-29T09:00:00+00:00", "updated_at": "2026-10-29T15:30:00+00:00",
  "url": "https://app.arqiflow.com/projects/prj_8c1d2e3f4a/work/wrk_3f9a1c2b7d"
}

Webhooks

Add an endpoint in Settings › Integrations › API and webhooks, or subscribe one with POST /v1/hooks. Arqiflow posts each event as it happens, whoever made the change: a person, their agent, the API or a form's public link. Only what the endpoint's person may see is sent.

task.createdA task was added
task.updatedA task's title, description, status, dates, people, stage, estimate or fields changed; data.changes says which
task.approvedA task was approved
project.createdA project was created
stage.signed_offA stage was signed off
time.loggedTime was logged; data.hours is what was added
form.responseA form was answered
file.addedA file was added to a task or a project
comment.createdA comment was written on a task
POST https://your-endpoint
Arqiflow-Event: task.approved
Arqiflow-Delivery: evt_0123456789abcdef
Arqiflow-Signature: t=1793664000,v1=5f2b…

{"id": "evt_0123456789abcdef", "type": "task.approved",
 "created_at": "2026-10-29T15:30:00+00:00", "firm_id": "org_…", "data": { …the task… }}

Answer with any 2xx within 10 seconds. Anything else is tried again after 1 minute, 5 minutes, 30 minutes, 2 hours, 8 hours and 24 hours; the delivery log in Settings shows each try and can resend. Answering 410 Gone switches the endpoint off.

Check the signature with the endpoint's secret: an HMAC-SHA256 of the time, a dot and the raw body.

// Node
const crypto = require("crypto");
function verify(secret, rawBody, header) {
  const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const mac = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300;
  return fresh && crypto.timingSafeEqual(Buffer.from(mac), Buffer.from(v1));
}
# Python
import hashlib, hmac, time
def verify(secret: str, raw_body: bytes, header: str) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    mac = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return abs(time.time() - int(parts["t"])) < 300 and hmac.compare_digest(mac, parts["v1"])

Zapier and Make

Search for Arqiflow in Zapier or Make and connect with your firm's address and an API key. Triggers start a zap or a scenario on each event above; actions add tasks, move them, comment, log time and create projects; searches find a task, a project or a person.

Building your own? Subscribe with POST /v1/hooks {"target_url": "...", "event": "task.approved"} and unsubscribe with DELETE /v1/hooks/{id}. The lists above are the polling triggers.

Bring your next project into Arqiflow.

Run your own projects and people in it free for 14 days, with no card. The agent comes with a plan.