Work API
Every Work action (23) and data model (5): endpoints, scopes, input, preconditions, events and examples.
Ask once: Era plans it, splits it across workers that run in parallel, and brings back finished work to use or publish.
Module code work · 23 actions · 5 data models · 18 events. A key or token never does more here than the person behind it can; row-level security applies exactly as in the app. Scopes: work (everything), work:read (read only) or work:<capability>.
Resources
| Resource | Table | List and read | POST | PATCH | DELETE |
|---|---|---|---|---|---|
shop_orders | shop_order | /api/v1/shop_orders | |||
shop_rules | shop_rule | /api/v1/shop_rules | |||
work_computer_forks | work_computer_fork | /api/v1/work_computer_forks | |||
work_jobs | work_job | /api/v1/work_jobs | |||
work_steps | work_step | /api/v1/work_steps |
Lists take limit (up to 200), cursor, order (e.g. -created_at), fields and q; every other query parameter is a column filter: ?status=paid, ?total[gte]=100, ?id[in]=a,b, ?x=null.
Actions
| Action | Needs | What it does |
|---|---|---|
work.add_step | work:write | Add a step to a plan |
work.answer_need | work:write | Answer a step that waits for you |
work.approve_plan | work:write | Approve a plan |
work.assign_job | work:write | Give a plan to someone |
work.change_step | work:write | Change a step |
work.message_step | work:write | Tell a working agent something |
work.propose_skill | work:handle | Offer what Era learned |
work.record_fork | work:handle | Record a borrowed computer |
work.record_shop_order | work:handle | Record an order Era placed |
work.record_step | work:handle | Record a step’s progress |
work.release_fork | work:write | Give a borrowed computer back |
work.replan_step | work:handle | Re-plan a step’s missing input |
work.request_fork | work:write | Borrow a copy of my cloud computer |
work.requeue_step | work:handle | Put a step back in line |
work.resume_job | work:write | Resume a plan |
work.retry_step | work:write | Try a step again |
work.review_skill | work:write | Decide what Era keeps |
work.set_limits | work:write | Change a plan’s time limit |
work.set_shop_rule | work:write | Set when Era buys without asking |
work.start_job | work:write | Start a plan |
work.stop_job | work:write | Stop a plan |
work.supervise_step | work:handle | Supervise a running step |
work.use_result | work:write | Use a result |
work.add_step
Add a step to a plan — "Şunu da ekle": one more step for a worker; it starts as soon as what it waits for is done.
Needs work:write · changes data
https://app.getera.io/api/v1/work_jobs/{id}/actions/add_step- Canonical address:
POST /api/v1/actions/work.add_step
Input
| Field | Type | Required | Notes |
|---|---|---|---|
jobId | uuid | yes | Filled from the path {id} · Plan · id of work_job |
title | string | yes | Step · max 200 |
worker | string | yes | Worker · dev | research | growth | marketing | creative | data | business | computer · max 20 |
instruction | string | What to do · max 8000 | |
run | object / array | How it runs | |
dependsOn | object / array | Waits for · Step ids of the same plan. | |
confirm | boolean | Ask me before it runs | |
note | string | What you said · max 500 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
not_found | The plan must exist in this workspace. |
unknown_worker | The step names one of the eight workers. |
unknown_executor | The step’s run names an executor Era has. |
unknown_credential | A credential step names a credential Era knows how to ask for. |
too_many_steps | A plan has at most 12 steps. |
bad_steps | The step needs a title. |
bad_dependency | A step can only wait for steps of the same plan. |
duplicate_step | The plan does not already have this work still to do or done. |
Events it publishes: work.step_changed
What it writes: work_step (insert) — Adds the step, queued; work_job (update) — Reopens the plan and notes what was said
curl -X POST https://app.getera.io/api/v1/work_jobs/WORK_JOB_ID/actions/add_step \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"title":"Step","worker":"Worker"}'{
"ok": true,
"result": "…",
"events": [
"work.step_changed"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workJobs.addStep("WORK_JOB_ID", {
title: "Step",
worker: "Worker"
})era work_jobs add_step WORK_JOB_ID \
--title "Step" \
--worker "Worker"{
"name": "era__work__add_step",
"arguments": {
"jobId": "WORK_JOB_ID",
"title": "Step",
"worker": "Worker"
}
}Errors: 401 no or expired credential · 403 the credential does not hold work:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, unknown_worker, unknown_executor, unknown_credential, too_many_steps, bad_steps, bad_dependency, duplicate_step · 429 slow down
work.answer_need
Answer a step that waits for you — Approve a risky step (it runs once) or decline it (it is skipped).
Needs work:write · changes data
https://app.getera.io/api/v1/work_steps/{id}/actions/answer_need- Canonical address:
POST /api/v1/actions/work.answer_need
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Step · id of work_step |
decision | string (enum) | yes | Decision · Allowed values: approve, deny |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
step_not_found | The step must exist in this workspace. |
nothing_to_answer | Only a step that waits for you can be answered. |
Events it publishes: work.step_changed, work.job_finished, work.needs_you
What it writes: work_step (update) — Queues or skips the step; work_job (update) — Updates the plan’s status
curl -X POST https://app.getera.io/api/v1/work_steps/WORK_STEP_ID/actions/answer_need \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"decision":"approve"}'{
"ok": true,
"result": "…",
"events": [
"work.step_changed",
"work.job_finished",
"work.needs_you"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workSteps.answerNeed("WORK_STEP_ID", {
decision: "approve"
})era work_steps answer_need WORK_STEP_ID \
--decision "approve"{
"name": "era__work__answer_need",
"arguments": {
"id": "WORK_STEP_ID",
"decision": "approve"
}
}Errors: 401 no or expired credential · 403 the credential does not hold work:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 step_not_found, nothing_to_answer · 429 slow down
work.approve_plan
Approve a plan — The go-ahead: the workers start on every step that waits for nothing.
Needs work:write · changes data
https://app.getera.io/api/v1/work_jobs/{id}/actions/approve_plan- Canonical address:
POST /api/v1/actions/work.approve_plan
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Plan · id of work_job |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
not_found | The plan must exist in this workspace. |
not_proposed | Only a plan waiting for approval can be approved. |
Events it publishes: work.plan_approved
What it writes: work_job (update) — Marks the plan approved and running
curl -X POST https://app.getera.io/api/v1/work_jobs/WORK_JOB_ID/actions/approve_plan \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{}'{
"ok": true,
"result": "…",
"events": [
"work.plan_approved"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workJobs.approvePlan("WORK_JOB_ID")era work_jobs approve_plan WORK_JOB_ID{
"name": "era__work__approve_plan",
"arguments": {
"id": "WORK_JOB_ID"
}
}Errors: 401 no or expired credential · 403 the credential does not hold work:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, not_proposed · 429 slow down
work.assign_job
Give a plan to someone — Gives a plan to a person or back to Era, and says who sees it: the whole workspace or only the people on it.
Needs work:write · changes data
https://app.getera.io/api/v1/work_jobs/{id}/actions/assign_job- Canonical address:
POST /api/v1/actions/work.assign_job
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Plan · id of work_job |
assigneeUserId | uuid | Give to · id of app_user | |
visibility | string (enum) | Who sees it · Allowed values: workspace, private |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
not_found | The plan must exist in this workspace. |
not_allowed | Only its author, its assignee or a work manager can hand it on. |
finished | A finished plan keeps who answered for it. |
not_a_member | A plan is given only to an active member of the workspace. |
Events it publishes: work.job_assigned
What it writes: work_job (update) — Writes who answers for the plan and who sees it
curl -X POST https://app.getera.io/api/v1/work_jobs/WORK_JOB_ID/actions/assign_job \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"assigneeUserId":"APP_USER_ID"}'{
"ok": true,
"result": "…",
"events": [
"work.job_assigned"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workJobs.assignJob("WORK_JOB_ID", {
assigneeUserId: "APP_USER_ID"
})era work_jobs assign_job WORK_JOB_ID \
--assignee-user-id "APP_USER_ID"{
"name": "era__work__assign_job",
"arguments": {
"id": "WORK_JOB_ID",
"assigneeUserId": "APP_USER_ID"
}
}Errors: 401 no or expired credential · 403 the credential does not hold work:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, not_allowed, finished, not_a_member · 429 slow down
work.change_step
Change a step — "Bunu değiştir": rewrites a step that has not started yet.
Needs work:write · changes data
https://app.getera.io/api/v1/work_steps/{id}/actions/change_step- Canonical address:
POST /api/v1/actions/work.change_step
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Step · id of work_step |
title | string | Step · max 200 | |
instruction | string | What to do · max 8000 | |
note | string | What you said · max 500 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
step_not_found | The step must exist in this workspace. |
step_started | A step that has started is not rewritten; a follow-up step is added instead. |
bad_steps | A step keeps a title. |
Events it publishes: work.step_changed
What it writes: work_step (update) — Rewrites the step; work_job (update) — Notes what was said
curl -X POST https://app.getera.io/api/v1/work_steps/WORK_STEP_ID/actions/change_step \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"title":"Step"}'{
"ok": true,
"result": "…",
"events": [
"work.step_changed"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workSteps.changeStep("WORK_STEP_ID", {
title: "Step"
})era work_steps change_step WORK_STEP_ID \
--title "Step"{
"name": "era__work__change_step",
"arguments": {
"id": "WORK_STEP_ID",
"title": "Step"
}
}Errors: 401 no or expired credential · 403 the credential does not hold work:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 step_not_found, step_started, bad_steps · 429 slow down
work.message_step
Tell a working agent something — Sends a message to an agent while it works on your computer ("also do this", "wait, do it like that"); it takes it into account at its next step.
Needs work:write · reaches outside (sends, publishes or charges)
https://app.getera.io/api/v1/work_steps/{id}/actions/message_step- Canonical address:
POST /api/v1/actions/work.message_step
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Step · id of work_step |
text | string | yes | Message |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
step_not_found | The step must exist in this workspace. |
empty_message | The message must say something. |
step_not_running | Only a step that is working (or waiting for you mid-run) can be told something. |
step_not_talkable | Only an agent running on a computer (a live harness session) can hear a message. |
Events it publishes: work.step_changed
What it writes: work_job (update) — Adds the message to the plan’s steering; work_step (update) — Shows the message as the step’s activity
curl -X POST https://app.getera.io/api/v1/work_steps/WORK_STEP_ID/actions/message_step \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"text":"Message"}'{
"ok": true,
"result": "…",
"events": [
"work.step_changed"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workSteps.messageStep("WORK_STEP_ID", {
text: "Message"
})era work_steps message_step WORK_STEP_ID \
--text "Message"{
"name": "era__work__message_step",
"arguments": {
"id": "WORK_STEP_ID",
"text": "Message"
}
}Errors: 401 no or expired credential · 403 the credential does not hold work:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 step_not_found, empty_message, step_not_running, step_not_talkable · 429 slow down
work.propose_skill
Offer what Era learned — "Era learned a new skill from this job — keep it?": the procedure that worked, waiting for the author. Machine-only.
Needs work:handle · changes data
403 machine_only).https://app.getera.io/api/v1/work_jobs/{id}/actions/propose_skill- Canonical address:
POST /api/v1/actions/work.propose_skill
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Plan · id of work_job |
name | string | Skill name · max 64 | |
description | string | What it does · max 600 | |
content | string | Steps · max 20000 | |
why | string | Learned from · max 600 | |
nothing | boolean | Nothing worth keeping |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
not_found | The plan must exist in this workspace. |
not_done | Era learns only from a plan that worked. |
already_proposed | One offer per plan. |
bad_skill | A kebab-case name, a line on what it does and the steps. |
Events it publishes: work.skill_proposed
What it writes: work_job (update) — Writes the offer on the plan
Errors: 401 no or expired credential · 403 the credential does not hold work:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, not_done, already_proposed, bad_skill · 429 slow down
work.record_fork
Record a borrowed computer — The computer worker reports a copy made, running, given back or failed, and its running time. Machine-only.
Needs work:handle · changes data
403 machine_only).https://app.getera.io/api/v1/work_computer_forks/{id}/actions/record_fork- Canonical address:
POST /api/v1/actions/work.record_fork
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Copy · id of work_computer_fork |
state | string | yes | State · forking | running | released | failed · max 20 |
externalId | string | Provider id · max 200 | |
deviceId | string | Runner · max 200 | |
error | string | Error · max 500 | |
addSeconds | number | Seconds it ran · min 0 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
fork_not_found | The copy must exist in this workspace. |
bad_state | The state must be a fork state. |
Events it publishes: work.fork_changed
What it writes: work_computer_fork (update) — Writes the copy’s state and time
Errors: 401 no or expired credential · 403 the credential does not hold work:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 fork_not_found, bad_state · 429 slow down
work.record_shop_order
Record an order Era placed — The shopping step’s report: what was ordered, the total, the card’s last four digits, the order number and — later — where it is. Never a card number. Machine-only.
Needs work:handle · changes data
403 machine_only).https://app.getera.io/api/v1/shop_orders/{id}/actions/record_shop_order- Canonical address:
POST /api/v1/actions/work.record_shop_order
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | Filled from the path {id} · Order (to update) · id of shop_order | |
store | string | yes | Store · max 40 |
request | string | What was asked · max 1000 | |
items | object / array | Items · [{ name, qty, price (kuruş), image, variant }] | |
totalMinor | number | Total (kuruş) · min 0 | |
deliveryFeeMinor | number | Delivery fee (kuruş) · min 0 | |
currency | string | Currency · max 3 | |
status | string | Status · placed | preparing | on_the_way | delivered | cancelled | unknown · max 20 | |
eta | string | Arrives · max 200 | |
courier | string | Courier · max 200 | |
orderNo | string | Order number · max 120 | |
trackUrl | string | Tracking page · max 2000 | |
cardLast4 | string | Card (last four digits) · Four digits; anything longer is refused. · max 40 | |
addressLabel | string | Delivery address · max 300 | |
space | string (enum) | Personal or business · Allowed values: personal, business | |
jobId | uuid | Plan · id of work_job | |
stepId | uuid | Step · id of work_step | |
autoApproved | boolean | Bought under the limit without asking | |
expenseId | uuid | Expense |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
bad_store | The store must be one Era shops at. |
bad_order | An order has 1–50 named items, whole kuruş amounts and a known status. |
card_number_refused | No card number is ever stored — only the last four digits. |
order_not_found | An update must name one of your own orders. |
Events it publishes: work.order_placed, work.order_updated
What it writes: shop_order (update) — Writes the order, or its tracking
Errors: 401 no or expired credential · 403 the credential does not hold work:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 bad_store, bad_order, card_number_refused, order_not_found · 429 slow down
work.record_step
Record a step’s progress — The engine’s report: taken, progress, what it is doing, what it needs, its result. Derives the plan’s status. Machine-only.
Needs work:handle · changes data
403 machine_only).https://app.getera.io/api/v1/work_steps/{id}/actions/record_step- Canonical address:
POST /api/v1/actions/work.record_step
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Step · id of work_step |
claim | boolean | Take it | |
status | string | Status · queued | running | needs_you | done | failed | skipped | stopped · max 20 | |
progress | number | Progress · min 0 · max 100 | |
activity | string | Doing now · max 300 | |
need | object / array | Waits for | |
executorRef | string | Executor record · max 200 | |
runtime | string | Runs on · max 300 | |
result | object / array | Result | |
error | string | Error · max 1000 | |
checkpoint | object / array | Checkpoint · Where the executor picks up after a restart: its record, its cursor, the text so far. |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
step_not_found | The step must exist in this workspace. |
bad_status | The status must be a step status. |
bad_transition | A finished step does not change; it is retried. |
bad_result | A result and a need are objects. |
bad_checkpoint | A checkpoint is an object of at most 40 000 characters. |
Events it publishes: work.step_changed, work.needs_you, work.job_finished, work.held
What it writes: work_step (update) — Writes the step’s progress, checkpoint and result; work_job (update) — Holds the plan at its time limit and derives its status from its steps
Errors: 401 no or expired credential · 403 the credential does not hold work:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 step_not_found, bad_status, bad_transition, bad_result, bad_checkpoint · 429 slow down
work.release_fork
Give a borrowed computer back — The step is done with its copy; the computer worker deletes it.
Needs work:write · changes data
https://app.getera.io/api/v1/work_computer_forks/{id}/actions/release_fork- Canonical address:
POST /api/v1/actions/work.release_fork
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Copy · id of work_computer_fork |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
fork_not_found | The copy must exist in this workspace. |
already_released | A copy is given back once. |
Events it publishes: work.fork_requested
What it writes: work_computer_fork (update) — Marks it to be deleted
curl -X POST https://app.getera.io/api/v1/work_computer_forks/WORK_COMPUTER_FORK_ID/actions/release_fork \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{}'{
"ok": true,
"result": "…",
"events": [
"work.fork_requested"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workComputerForks.releaseFork("WORK_COMPUTER_FORK_ID")era work_computer_forks release_fork WORK_COMPUTER_FORK_ID{
"name": "era__work__release_fork",
"arguments": {
"id": "WORK_COMPUTER_FORK_ID"
}
}Errors: 401 no or expired credential · 403 the credential does not hold work:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 fork_not_found, already_released · 429 slow down
work.replan_step
Re-plan a step’s missing input — A step that found none of the input it needs (no rows to export or import) gets one step that produces it, and waits for it. Machine-only.
Needs work:handle · changes data
403 machine_only).https://app.getera.io/api/v1/work_steps/{id}/actions/replan_step- Canonical address:
POST /api/v1/actions/work.replan_step
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Step · id of work_step |
title | string | yes | New step · max 200 |
worker | string | yes | Worker · max 20 |
instruction | string | What to do · max 8000 | |
run | object / array | How it runs | |
reason | string | Why · max 500 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
step_not_found | The step must exist in this workspace. |
not_running | Only a running step asks for its missing input. |
already_replanned | A step re-plans its input once; a second miss is a failure. |
unknown_worker | The new step names one of the eight workers. |
unknown_executor | The new step’s run names an executor Era has. |
unknown_credential | A credential step names a credential Era knows how to ask for. |
too_many_steps | A plan has at most 12 steps. |
bad_steps | The new step needs a title. |
Events it publishes: work.step_changed, work.needs_you, work.job_finished
What it writes: work_step (insert) — Adds the step that produces the missing input; work_step (update) — The consumer waits for it and goes back in line; work_job (update) — Notes the re-plan and derives the plan’s status
Errors: 401 no or expired credential · 403 the credential does not hold work:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 step_not_found, not_running, already_replanned, unknown_worker, unknown_executor, unknown_credential, too_many_steps, bad_steps · 429 slow down
work.request_fork
Borrow a copy of my cloud computer — One forked copy of your own signed-in cloud computer for one step, so parallel workers each get their own machine.
Needs work:write · changes data
https://app.getera.io/api/v1/work_computer_forks/actions/request_fork- Canonical address:
POST /api/v1/actions/work.request_fork
Input
| Field | Type | Required | Notes |
|---|---|---|---|
stepId | uuid | yes | Step · id of work_step |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
step_not_found | The step must exist in this workspace. |
not_found | The step’s plan must exist. |
not_owner | Only the plan’s author lends a copy of their own computer. |
no_base_computer | The author needs a cloud computer that is running or asleep. |
fork_limit | At most the workspace plan’s "at once" number of copies per job. |
hours_used_up | The month’s cloud computer hours must not be used up. |
Events it publishes: work.fork_requested
What it writes: work_computer_fork (insert) — Asks the computer worker for a copy
curl -X POST https://app.getera.io/api/v1/work_computer_forks/actions/request_fork \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"stepId":"WORK_STEP_ID"}'{
"ok": true,
"result": "…",
"events": [
"work.fork_requested"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workComputerForks.requestFork({
stepId: "WORK_STEP_ID"
})era work_computer_forks request_fork \
--step-id "WORK_STEP_ID"{
"name": "era__work__request_fork",
"arguments": {
"stepId": "WORK_STEP_ID"
}
}Errors: 401 no or expired credential · 403 the credential does not hold work:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 step_not_found, not_found, not_owner, no_base_computer, fork_limit, hours_used_up · 429 slow down
work.requeue_step
Put a step back in line — A step whose process went away goes back in line; the next taker resumes from its checkpoint. Machine-only.
Needs work:handle · changes data
403 machine_only).https://app.getera.io/api/v1/work_steps/{id}/actions/requeue_step- Canonical address:
POST /api/v1/actions/work.requeue_step
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Step · id of work_step |
reason | string | Why · max 300 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
step_not_found | The step must exist in this workspace. |
not_running | Only a running step goes back in line. |
Events it publishes: work.step_changed, work.needs_you, work.job_finished
What it writes: work_step (update) — Queues the step, keeping its checkpoint; work_job (update) — Derives the plan’s status
Errors: 401 no or expired credential · 403 the credential does not hold work:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 step_not_found, not_running · 429 slow down
work.resume_job
Resume a plan — Puts a stopped or failed plan’s unfinished steps back in line.
Needs work:write · changes data
https://app.getera.io/api/v1/work_jobs/{id}/actions/resume_job- Canonical address:
POST /api/v1/actions/work.resume_job
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Plan · id of work_job |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
not_found | The plan must exist in this workspace. |
not_stopped | Only a stopped or failed plan can be resumed. |
Events it publishes: work.job_resumed
What it writes: work_step (update) — Queues the stopped and failed steps again; work_job (update) — Marks the plan running
curl -X POST https://app.getera.io/api/v1/work_jobs/WORK_JOB_ID/actions/resume_job \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{}'{
"ok": true,
"result": "…",
"events": [
"work.job_resumed"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workJobs.resumeJob("WORK_JOB_ID")era work_jobs resume_job WORK_JOB_ID{
"name": "era__work__resume_job",
"arguments": {
"id": "WORK_JOB_ID"
}
}Errors: 401 no or expired credential · 403 the credential does not hold work:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, not_stopped · 429 slow down
work.retry_step
Try a step again — Puts a failed, stopped or skipped step back in line.
Needs work:write · changes data
https://app.getera.io/api/v1/work_steps/{id}/actions/retry_step- Canonical address:
POST /api/v1/actions/work.retry_step
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Step · id of work_step |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
step_not_found | The step must exist in this workspace. |
not_failed | Only a failed, stopped or skipped step can be tried again. |
Events it publishes: work.step_changed
What it writes: work_step (update) — Queues the step again; work_job (update) — Marks the plan running
curl -X POST https://app.getera.io/api/v1/work_steps/WORK_STEP_ID/actions/retry_step \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{}'{
"ok": true,
"result": "…",
"events": [
"work.step_changed"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workSteps.retryStep("WORK_STEP_ID")era work_steps retry_step WORK_STEP_ID{
"name": "era__work__retry_step",
"arguments": {
"id": "WORK_STEP_ID"
}
}Errors: 401 no or expired credential · 403 the credential does not hold work:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 step_not_found, not_failed · 429 slow down
work.review_skill
Decide what Era keeps — Keep it (the workspace’s Eras may use it), keep it private (only yours), correct it, or forget it.
Needs work:write · changes data
https://app.getera.io/api/v1/work_jobs/{id}/actions/review_skill- Canonical address:
POST /api/v1/actions/work.review_skill
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Plan · id of work_job |
decision | string (enum) | yes | Decision · Allowed values: keep, private, forget |
content | string | Corrected steps · max 20000 | |
skillId | string | Saved skill · max 200 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
not_found | The plan must exist in this workspace. |
no_proposal | Era must have offered something from this plan. |
already_reviewed | One decision per offer. |
not_owner | The plan’s author decides. |
bad_skill | A kept skill keeps its steps. |
Events it publishes: work.skill_reviewed
What it writes: work_job (update) — Records the decision
curl -X POST https://app.getera.io/api/v1/work_jobs/WORK_JOB_ID/actions/review_skill \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"decision":"keep"}'{
"ok": true,
"result": "…",
"events": [
"work.skill_reviewed"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workJobs.reviewSkill("WORK_JOB_ID", {
decision: "keep"
})era work_jobs review_skill WORK_JOB_ID \
--decision "keep"{
"name": "era__work__review_skill",
"arguments": {
"id": "WORK_JOB_ID",
"decision": "keep"
}
}Errors: 401 no or expired credential · 403 the credential does not hold work:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, no_proposal, already_reviewed, not_owner, bad_skill · 429 slow down
work.set_limits
Change a plan’s time limit — How many minutes a plan may run. A plan held at its time limit goes on from where it stopped.
Needs work:write · changes data
https://app.getera.io/api/v1/work_jobs/{id}/actions/set_limits- Canonical address:
POST /api/v1/actions/work.set_limits
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Plan · id of work_job |
maxMinutes | number | Time limit (minutes from the start, empty = no cap) |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
not_found | The plan must exist in this workspace. |
already_finished | A finished plan has no limits to change. |
bad_limits | A time limit is 1 minute to a week. |
still_over | A new time limit must end after now. |
Events it publishes: work.limits_changed, work.needs_you, work.job_finished
What it writes: work_job (update) — Writes the time limit; lifts the hold it caused
curl -X POST https://app.getera.io/api/v1/work_jobs/WORK_JOB_ID/actions/set_limits \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"maxMinutes":1}'{
"ok": true,
"result": "…",
"events": [
"work.limits_changed",
"work.needs_you",
"work.job_finished"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workJobs.setLimits("WORK_JOB_ID", {
maxMinutes: 1
})era work_jobs set_limits WORK_JOB_ID \
--max-minutes 1{
"name": "era__work__set_limits",
"arguments": {
"id": "WORK_JOB_ID",
"maxMinutes": 1
}
}Errors: 401 no or expired credential · 403 the credential does not hold work:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, already_finished, bad_limits, still_over · 429 slow down
work.set_shop_rule
Set when Era buys without asking — Purchases up to this amount at this store (or every store) go through without the confirmation card. Empty or 0 = ask every time, which is the default.
Needs work:write · changes data
https://app.getera.io/api/v1/shop_rules/actions/set_shop_rule- Canonical address:
POST /api/v1/actions/work.set_shop_rule
Input
| Field | Type | Required | Notes |
|---|---|---|---|
store | string | yes | Store · getir | trendyol | yemeksepeti | hepsiburada | amazon_tr | migros | mock | * (every store) · max 40 |
askAboveMinor | number | Buy without asking up to (kuruş) · Whole kuruş, 0 to 10 000 000 (100 000 TL); 0 or empty = ask every time. | |
currency | string | Currency · max 3 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
bad_store | The store must be one Era shops at, or * for every store. |
bad_amount | The limit is a whole amount from 1 kuruş to 100 000 TL. |
Events it publishes: work.shop_rule_changed
What it writes: shop_rule (update) — Writes or clears the person’s limit for that store
curl -X POST https://app.getera.io/api/v1/shop_rules/actions/set_shop_rule \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"store":"Store"}'{
"ok": true,
"result": "…",
"events": [
"work.shop_rule_changed"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.shopRules.setShopRule({
store: "Store"
})era shop_rules set_shop_rule \
--store "Store"{
"name": "era__work__set_shop_rule",
"arguments": {
"store": "Store"
}
}Errors: 401 no or expired credential · 403 the credential does not hold work:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 bad_store, bad_amount · 429 slow down
work.start_job
Start a plan — Era’s plan for one ask: numbered steps, each for a worker (dev, research, growth, marketing, creative, data, business, computer), run in parallel where nothing waits.
Needs work:write · changes data
https://app.getera.io/api/v1/work_jobs/actions/start_job- Canonical address:
POST /api/v1/actions/work.start_job
Input
| Field | Type | Required | Notes |
|---|---|---|---|
title | string | yes | Name · max 200 |
goal | string | What was asked · max 8000 | |
mode | string (enum) | Started from · Allowed values: chat, background, scheduled | |
conversationId | string | Conversation · max 200 | |
agentRef | string | Era · max 200 | |
askFirst | boolean | Wait for my approval of the plan | |
nextStep | string | Suggested next step · max 300 | |
scopeCtx | object / array | Scope · The wire scope the workers run with (ids only). | |
steps | object / array | yes | Steps · [{ title, worker, instruction, run?: { kind, … }, dependsOn?: [earlier step numbers], confirm? }] |
deliverable | string | Deliver · none (the results) | report (a report as PDF + slides) · max 20 | |
maxMinutes | number | Time limit (minutes) |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
bad_limits | A time limit is 1 minute to a week. |
bad_deliverable | A plan delivers its results, or a report. |
empty_title | A plan needs a name. |
no_steps | A plan needs at least one step. |
too_many_steps | A plan has at most 12 steps. |
bad_steps | Every step is an object with a title. |
unknown_worker | Every step names one of the eight workers. |
unknown_executor | A step’s run names an executor Era has. |
unknown_credential | A credential step names a credential Era knows how to ask for. |
bad_dependency | A step can only wait for an earlier step of the same plan. |
duplicate_step | A plan does the same work once: no two steps with one title, export format or Sales import. |
Events it publishes: work.job_started
What it writes: work_job (insert) — Writes the plan, running or waiting for approval; work_step (insert) — Writes its steps, queued
curl -X POST https://app.getera.io/api/v1/work_jobs/actions/start_job \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"title":"Name","steps":{}}'{
"ok": true,
"result": "…",
"events": [
"work.job_started"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workJobs.startJob({
title: "Name",
steps: {}
})era work_jobs start_job --data '{"title":"Name","steps":{}}'{
"name": "era__work__start_job",
"arguments": {
"title": "Name",
"steps": {}
}
}Errors: 401 no or expired credential · 403 the credential does not hold work:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 bad_limits, bad_deliverable, empty_title, no_steps, too_many_steps, bad_steps, unknown_worker, unknown_executor, unknown_credential, bad_dependency, duplicate_step · 429 slow down
work.stop_job
Stop a plan — "Dur": every step that has not finished stops; what is done stays done.
Needs work:write · changes data
https://app.getera.io/api/v1/work_jobs/{id}/actions/stop_job- Canonical address:
POST /api/v1/actions/work.stop_job
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Plan · id of work_job |
reason | string | Why · max 500 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
not_found | The plan must exist in this workspace. |
already_finished | A finished plan cannot be stopped. |
Events it publishes: work.job_stopped
What it writes: work_step (update) — Stops every unfinished step; work_job (update) — Marks the plan stopped and notes it
curl -X POST https://app.getera.io/api/v1/work_jobs/WORK_JOB_ID/actions/stop_job \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"reason":"Why"}'{
"ok": true,
"result": "…",
"events": [
"work.job_stopped"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workJobs.stopJob("WORK_JOB_ID", {
reason: "Why"
})era work_jobs stop_job WORK_JOB_ID \
--reason "Why"{
"name": "era__work__stop_job",
"arguments": {
"id": "WORK_JOB_ID",
"reason": "Why"
}
}Errors: 401 no or expired credential · 403 the credential does not hold work:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, already_finished · 429 slow down
work.supervise_step
Supervise a running step — The work sweep’s ladder: nudge a quiet step, interrupt and send it again (twice at most), hand it to you when it stays stuck, remind you once about an unanswered approval. Machine-only.
Needs work:handle · changes data
403 machine_only).https://app.getera.io/api/v1/work_steps/{id}/actions/supervise_step- Canonical address:
POST /api/v1/actions/work.supervise_step
Input
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | Filled from the path {id} · Step · id of work_step |
op | string | yes | Ladder step · nudge | recover | give_up | remind · max 20 |
quietMinutes | number | Quiet for (minutes) · min 0 | |
reason | string | Why · max 300 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
step_not_found | The step must exist in this workspace. |
bad_supervision | Nudge, recover, give up or remind. |
not_running | Only a running step is nudged, restarted or handed to you. |
recoveries_used | A step is restarted at most twice; then it waits for you. |
not_waiting | Only a step that waits for you is reminded about. |
already_reminded | One reminder per wait. |
Events it publishes: work.step_changed, work.needs_you, work.job_finished
What it writes: work_step (update) — Writes the ladder’s state; queues a restarted step (keeping its checkpoint) or hands a stuck one to you; work_job (update) — Derives the plan’s status
Errors: 401 no or expired credential · 403 the credential does not hold work:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 step_not_found, bad_supervision, not_running, recoveries_used, not_waiting, already_reminded · 429 slow down
work.use_result
Use a result — Records that a result card was used or published (the card’s own action runs as you).
Needs work:write · changes data
https://app.getera.io/api/v1/work_steps/{id}/actions/use_result- Canonical address:
POST /api/v1/actions/work.use_result
Input
| Field | Type | Required | Notes |
|---|---|---|---|
stepId | uuid | yes | Filled from the path {id} · Step · id of work_step |
card | number | yes | Result · min 0 · max 50 |
kind | string (enum) | yes | What · Allowed values: use, publish, approve, open |
target | string | Where · max 200 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
step_not_found | The step must exist in this workspace. |
no_such_card | The result must be one of the step’s cards. |
Events it publishes: work.result_used
What it writes: work_step (update) — Marks the card used or live
curl -X POST https://app.getera.io/api/v1/work_steps/WORK_STEP_ID/actions/use_result \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"card":1,"kind":"use"}'{
"ok": true,
"result": "…",
"events": [
"work.result_used"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.workSteps.useResult("WORK_STEP_ID", {
card: 1,
kind: "use"
})era work_steps use_result WORK_STEP_ID \
--card 1 \
--kind "use"{
"name": "era__work__use_result",
"arguments": {
"stepId": "WORK_STEP_ID",
"card": 1,
"kind": "use"
}
}Errors: 401 no or expired credential · 403 the credential does not hold work:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 step_not_found, no_such_card · 429 slow down
Data models
ShopOrder
Table shop_order · Resource shop_orders
GET /api/v1/shop_ordersGET /api/v1/shop_orders/{id}
| Column | Type | Nullable | Allowed values | References |
|---|---|---|---|---|
id | string (uuid) · uuid | |||
organization_id | string (uuid) · uuid | organization | ||
workspace_id | string (uuid) · uuid | workspace | ||
user_id | string (uuid) · uuid | app_user | ||
store | string · text | |||
request | string · text | |||
items | object · jsonb | |||
total_minor | string (int64) · int8 | yes | ||
delivery_fee_minor | string (int64) · int8 | yes | ||
currency | string · text | |||
status | string · text | placed, preparing, on_the_way, delivered, cancelled, unknown | ||
status_at | string (date-time) · timestamptz | |||
eta | string · text | yes | ||
courier | string · text | yes | ||
order_no | string · text | yes | ||
track_url | string · text | yes | ||
card_last4 | string · text | yes | ||
address_label | string · text | yes | ||
space | string · text | personal, business | ||
expense_id | string (uuid) · uuid | yes | ||
job_id | string (uuid) · uuid | yes | work_job | |
step_id | string (uuid) · uuid | yes | work_step | |
auto_approved | boolean · bool | |||
visibility | string · text | private, workspace | ||
placed_at | string (date-time) · timestamptz | |||
created_at | string (date-time) · timestamptz | |||
updated_at | string (date-time) · timestamptz |
Primary key: id
Checks:
CHECK (((address_label IS NULL) OR (length(address_label) <= 300)))CHECK (((card_last4 IS NULL) OR (card_last4 ~ '^[0-9]{4}$'::text)))CHECK (((courier IS NULL) OR (length(courier) <= 200)))CHECK ((currency ~ '^[A-Z]{3}$'::text))CHECK (((delivery_fee_minor IS NULL) OR (delivery_fee_minor >= 0)))CHECK (((eta IS NULL) OR (length(eta) <= 200)))CHECK ((jsonb_typeof(items) = 'array'::text))CHECK (((order_no IS NULL) OR (length(order_no) <= 120)))CHECK ((length(request) <= 1000))CHECK ((store ~ '^[a-z_]{2,40}$'::text))CHECK (((total_minor IS NULL) OR (total_minor >= 0)))CHECK (((track_url IS NULL) OR (length(track_url) <= 2000)))
ShopRule
Table shop_rule · Resource shop_rules
GET /api/v1/shop_rulesGET /api/v1/shop_rules/{id}
| Column | Type | Nullable | Allowed values | References |
|---|---|---|---|---|
id | string (uuid) · uuid | |||
organization_id | string (uuid) · uuid | organization | ||
workspace_id | string (uuid) · uuid | workspace | ||
user_id | string (uuid) · uuid | app_user | ||
store | string · text | |||
ask_above_minor | string (int64) · int8 | |||
currency | string · text | |||
visibility | string · text | private, workspace | ||
created_at | string (date-time) · timestamptz | |||
updated_at | string (date-time) · timestamptz |
Primary key: id
Unique: workspace_id, user_id, store
Checks:
CHECK (((ask_above_minor > 0) AND (ask_above_minor <= 10000000)))CHECK ((currency ~ '^[A-Z]{3}$'::text))CHECK ((store ~ '^(\*\|[a-z_]{2,40})$'::text))
WorkComputerFork
Table work_computer_fork · Resource work_computer_forks
GET /api/v1/work_computer_forksGET /api/v1/work_computer_forks/{id}
| Column | Type | Nullable | Allowed values | References |
|---|---|---|---|---|
id | string (uuid) · uuid | |||
organization_id | string (uuid) · uuid | organization | ||
workspace_id | string (uuid) · uuid | workspace | ||
job_id | string (uuid) · uuid | work_job | ||
step_id | string (uuid) · uuid | work_step | ||
owner_user_id | string (uuid) · uuid | app_user | ||
base_machine_id | string (uuid) · uuid | computer_machine | ||
provider | string · text | |||
external_id | string · text | yes | ||
device_id | string · text | yes | ||
state | string · text | requested, forking, running, releasing, released, failed | ||
error | string · text | yes | ||
seconds_used | string (int64) · int8 | |||
started_at | string (date-time) · timestamptz | yes | ||
released_at | string (date-time) · timestamptz | yes | ||
created_at | string (date-time) · timestamptz | |||
updated_at | string (date-time) · timestamptz |
Primary key: id
Checks:
CHECK (((device_id IS NULL) OR (length(device_id) <= 200)))CHECK (((error IS NULL) OR (length(error) <= 500)))CHECK (((external_id IS NULL) OR (length(external_id) <= 200)))CHECK ((seconds_used >= 0))
WorkJob
Table work_job · Resource work_jobs
GET /api/v1/work_jobsGET /api/v1/work_jobs/{id}
| Column | Type | Nullable | Allowed values | References |
|---|---|---|---|---|
id | string (uuid) · uuid | |||
organization_id | string (uuid) · uuid | organization | ||
workspace_id | string (uuid) · uuid | workspace | ||
title | string · text | |||
goal | string · text | |||
status | string · text | proposed, running, needs_you, done, failed, stopped | ||
mode | string · text | chat, background, scheduled | ||
conversation_id | string · text | yes | ||
agent_ref | string · text | yes | ||
ask_first | boolean · bool | |||
plan_approved_at | string (date-time) · timestamptz | yes | ||
next_step | string · text | yes | ||
steering | object · jsonb | |||
scope_ctx | object · jsonb | |||
summary | string · text | yes | ||
created_by | string (uuid) · uuid | app_user | ||
created_at | string (date-time) · timestamptz | |||
updated_at | string (date-time) · timestamptz | |||
finished_at | string (date-time) · timestamptz | yes | ||
deliverable | string · text | none, report | ||
max_minutes | integer · int4 | yes | ||
deadline_at | string (date-time) · timestamptz | yes | ||
hold | object · jsonb | yes | ||
learned | object · jsonb | yes | ||
assignee_user_id | string (uuid) · uuid | yes | app_user | |
visibility | string · text | private, workspace |
Primary key: id
Checks:
CHECK ((length(goal) <= 8000))CHECK (((hold IS NULL) OR ((jsonb_typeof(hold) = 'object'::text) AND (hold ? 'kind'::text))))CHECK (((learned IS NULL) OR ((jsonb_typeof(learned) = 'object'::text) AND (learned ? 'status'::text))))CHECK (((max_minutes IS NULL) OR ((max_minutes >= 1) AND (max_minutes <= 10080))))CHECK (((next_step IS NULL) OR (length(next_step) <= 300)))CHECK ((jsonb_typeof(scope_ctx) = 'object'::text))CHECK ((jsonb_typeof(steering) = 'array'::text))CHECK (((summary IS NULL) OR (length(summary) <= 4000)))CHECK (((length(btrim(title)) >= 1) AND (length(btrim(title)) <= 200)))
WorkStep
Table work_step · Resource work_steps
GET /api/v1/work_stepsGET /api/v1/work_steps/{id}
| Column | Type | Nullable | Allowed values | References |
|---|---|---|---|---|
id | string (uuid) · uuid | |||
organization_id | string (uuid) · uuid | organization | ||
workspace_id | string (uuid) · uuid | workspace | ||
job_id | string (uuid) · uuid | work_job | ||
position | integer · int4 | |||
title | string · text | |||
instruction | string · text | |||
worker | string · text | dev, research, growth, marketing, creative, data, business, computer | ||
run | object · jsonb | |||
depends_on | string[] · uuid[] | |||
confirm | boolean · bool | |||
status | string · text | queued, running, needs_you, done, failed, skipped, stopped | ||
progress | integer · int4 | |||
activity | string · text | yes | ||
need | object · jsonb | yes | ||
executor_ref | string · text | yes | ||
runtime | string · text | yes | ||
result | object · jsonb | |||
error | string · text | yes | ||
started_at | string (date-time) · timestamptz | yes | ||
finished_at | string (date-time) · timestamptz | yes | ||
heartbeat_at | string (date-time) · timestamptz | yes | ||
created_at | string (date-time) · timestamptz | |||
updated_at | string (date-time) · timestamptz | |||
checkpoint | object · jsonb | yes | ||
checkpoint_at | string (date-time) · timestamptz | yes | ||
attempts | integer · int4 | |||
supervision | object · jsonb | yes |
Primary key: id
Checks:
CHECK (((activity IS NULL) OR (length(activity) <= 300)))CHECK (((attempts >= 0) AND (attempts <= 1000)))CHECK (((checkpoint IS NULL) OR (jsonb_typeof(checkpoint) = 'object'::text)))CHECK (((error IS NULL) OR (length(error) <= 1000)))CHECK (((executor_ref IS NULL) OR (length(executor_ref) <= 200)))CHECK ((length(instruction) <= 8000))CHECK (((need IS NULL) OR (jsonb_typeof(need) = 'object'::text)))CHECK ((("position" >= 1) AND ("position" <= 50)))CHECK (((progress >= 0) AND (progress <= 100)))CHECK ((jsonb_typeof(result) = 'object'::text))CHECK (((jsonb_typeof(run) = 'object'::text) AND (run ? 'kind'::text)))CHECK (((runtime IS NULL) OR (length(runtime) <= 300)))CHECK (((supervision IS NULL) OR (jsonb_typeof(supervision) = 'object'::text)))CHECK (((length(btrim(title)) >= 1) AND (length(btrim(title)) <= 200)))
Events
Workflows and webhooks react to these events.
| Event | What happens | Payload |
|---|---|---|
work.fork_changed | A borrowed cloud computer was made, started, given back or failed. | id, state, jobId, stepId |
work.fork_requested | A step asked for (or gave back) a copy of its author’s cloud computer. | id, op, jobId, stepId |
work.held | A plan reached its time limit and waits for the person. | id, title, kind, steps |
work.job_assigned | A plan was given to a person or back to Era, or who sees it changed. | id, title, assigneeUserId, visibility, link, recipientUserId |
work.job_finished | A plan finished (done, failed or stopped). | id, title, status, message, link, recipientUserId |
work.job_resumed | A stopped plan was resumed. | id, title, steps |
work.job_started | Era started a plan (or proposed one for approval). | id, title, steps, status, recipientUserId |
work.job_stopped | Somebody stopped a plan. | id, title |
work.limits_changed | A plan’s time limit changed. | id, maxMinutes, resumed |
work.needs_you | A plan waits for you — an approval, a credential, a computer, or more time. | id, title, message, link, recipientUserId |
work.order_placed | Era placed an order in the person’s store account. | id, store, title, total, currency, status, eta, recipientUserId |
work.order_updated | An order Era placed moved on (preparing, on the way, delivered). | id, store, status, eta, recipientUserId |
work.plan_approved | A plan was approved; its workers start. | id, title |
work.result_used | A result card was used or published. | id, jobId, card, kind, target |
work.shop_rule_changed | Somebody changed when Era buys without asking. | store, askAboveMinor |
work.skill_proposed | Era learned a procedure from a plan that worked and asks whether to keep it. | id, title, name, message, link, recipientUserId |
work.skill_reviewed | The author kept, kept private or forgot what Era learned. | id, decision, skillId |
work.step_changed | A step was taken, finished, added, changed or answered. | id, jobId, status |