API concepts
The words the Syndai coding API uses: workspace, project, run, phase, result, questions, checks, webhooks and the idempotency key.
These are the terms the rest of the API docs use.
Workspace
A workspace is your account in Syndai. The API calls it a customer, so you see customer_id in responses. API keys, projects, webhook endpoints, members and your plan all belong to one workspace. Every API call acts as the workspace that owns the key.
A member has one of four roles: owner, admin, member or viewer.
Project
A project is one code repository. Runs refer to it by coding_repository_id. It is either hosted by Syndai or connected from GitHub, and its provider field says which. GET /repos lists the projects a key can see.
Run
A run is one task on one project. It starts from a prompt and moves through phases that Syndai owns. It ends as completed, failed or cancelled. Runs are the main resource of the API.
Phase
run.current_phase names the step a run is on. Each change sends a coding.run.phase_changed event. Today the phases are intake, provision, clarify, plan, execute, validate, docs, commit, preflight and pr, then one of the three end phases.
Treat the phase as an open string. New phases can appear. Match completed, failed and cancelled as the end, and do not list every other phase in your code.
Result kind
run.result_kind says what a completed run produced:
| value | meaning |
|---|---|
pull_request | the run opened a pull request; run.pr_url links to it |
no_changes | the run found nothing to change |
null | the run has not completed, or ended some other way |
Final response
The run detail route returns final_response, the run's own words about what it did. Its status is one of:
| status | meaning |
|---|---|
pending | the run is still going |
ready | content holds the text |
failed | writing the response failed; error_code says so |
unavailable | the run ended and has no response |
A failed or cancelled run also gets a response that explains why it stopped. Right after a run ends, the status can read unavailable for a moment while the text is saved. The coding.run.final_response_ready event is the signal to read it.
The text is only on GET /runs/{id}. List rows, events and webhooks never carry it.
Readiness
run.readiness shows how the first read of your prompt went. readiness is green when the prompt was clear. It is red when Syndai wants you to confirm something first, and clarifying_questions lists what it asks. Treat it as an open string.
Questions
When a run needs a person, it pauses and sends coding.run.question_required. The run detail lists the open asks in pending_hitl_requests. Each one has a hitl_request_id and inputs. Answer with POST /runs/{id}/responses, as the quickstart shows.
A question at intake waits up to 24 hours. Then the run goes on with its best reading of the prompt.
Validation level
policy_config.validation.level sets how much testing Syndai runs after the code is written. It is smoke, standard or strict, and standard is the default. Syndai picks the test tools for your stack. You never name a test runner. See Validation.
Review gate
A review gate is a check that reads the plan or the change and gives a verdict. It never edits code. The gates are planning_review, adversarial_review, security_review and preflight. Every run needs planning_review, security_review and preflight. Your policy can ask for adversarial_review too.
A gate's status is one of pending, running, passed, failed, waived, blocked or cancelled. A required gate that fails holds the run back from finishing. See Review gates.
Webhook event
A webhook event is a signed HTTP POST that Syndai sends to your endpoint when a run changes. Each one has an event type, such as coding.run.completed. It is signed with HMAC-SHA256 in the X-Syndai-Signature header. See Webhooks for the full list and how to check a signature.
Idempotency key
external_request_id is required on POST /runs. Syndai keeps one run per key in each workspace.
- Send the same key and the same body again, and you get
409 IDEMPOTENCY_REPLAY. The body hasexisting_run_id, and theLocationheader points at the run. No new run starts and nothing more is charged. - Send the same key with a different body, and you get
409 CONFLICT.
So after a network timeout, retry with the same key and follow existing_run_id. A key is used up for good once a run has it. A follow-up is a new run, so it needs a new key.