Reference
Every route, generated from the OpenAPI document. Base URL: https://api.forge.team/v1
POST/v1/conversations
Start a conversation. Creates a conversation and sends its first message. The response shape follows reply and stream.
Body
cwdoptionalstring The working folder the agent starts in. Omit for your default.replyoptional"none" | "optional" | "required" Default optional.streamoptionalboolean Stream the agent's messages as Server-Sent Events instead of one JSON body. Default false.textstring The first message. Up to 100,000 characters.titleoptionalstring A title for the conversation. Omit and Forge names it from the first message.Response
conversationIdstringmessageIdstring The id of the message you sent.repliesoptionalReply[] The agent's messages, in order. Absent on a 202 (reply: "none").timedOutoptionalboolean True when the 10-minute wait ran out before the turn ended.Try it
GET/v1/conversations
List conversations. Your active conversations, newest first. A ticket is one row.
Parameters
limitoptionalnumber · query 1 to 100, default 20.Response
conversationsConversation[]Try it
GET/v1/conversations/{conversationId}
Get a conversation. Whether the agent is working, what waits on you, and the end of its newest message.
Parameters
conversationIdstring · pathResponse
acceptedInputsnumber Messages accepted that the next turn has not read yet.busybooleanconversationIdstringdeferredboolean The next turn is waiting for its turn to run.deferredBy"account_cap" | "database" | "demand" | "memory" | "net" | "plan_cap" | "priority" | "provider" | "slot" | "user_cap" | "waitlist" | nulldeferredSincenumber | nulletaSecondsnumber | null The measured time left, in seconds, when there is evidence for one.lastAssistantTextstring | null The end of the agent's newest message.nextAttemptAtMsnumber | nullpendingGatesPendingGate[]phaseRunPhaserunStatestringstage"done" | "execute" | "finalise" | "plan" | "review" | nullstateConversationState | nullstatusstring | null The agent's own one-line status, when it set one.titlestringupdatedAtMsnumber Epoch milliseconds.waitingForstring | null What the deferred turn waits on, in plain words.Try it
POST/v1/messages
Send a message. Sends a message to a conversation. The response shape follows reply and stream.
Body
conversationIdstringreplyoptional"none" | "optional" | "required" Default optional.streamoptionalboolean Stream the agent's messages as Server-Sent Events instead of one JSON body. Default false.textstring The message. Up to 100,000 characters.Response
conversationIdstringmessageIdstring The id of the message you sent.repliesoptionalReply[] The agent's messages, in order. Absent on a 202 (reply: "none").timedOutoptionalboolean True when the 10-minute wait ran out before the turn ended.Try it
GET/v1/conversations/{conversationId}/messages
List messages. What was said in a conversation, newest page first.
Parameters
conversationIdstring · pathbeforeoptionalstring · query From the previous page, to read the messages before it. Opaque: pass it back as given.limitoptionalnumber · query 1 to 1,000, default 50.Response
beforestring | null Pass as before to read older messages; null when this page reaches the start.conversationIdstringmessagesMessage[]Try it
Types
ApiError
codeoptionalstringerrorstringConversation
One row per piece of work: a ticket with several member conversations is one row, addressed by the member it is live on.
busyboolean The agent is working right now.conversationIdstring The conversation to send to. For a ticket, its live member.cwdstring | nullmembersoptionalConversationMember[]modelstring | nullstage"done" | "execute" | "finalise" | "plan" | "review" | nullticketIdoptionalstringtitlestringupdatedAtMsnumber Epoch milliseconds.ConversationList
conversationsConversation[]ConversationMember
conversationIdstringrolestring | nulltitlestringConversationPath
conversationIdstringConversationState
bucketConvoBucketreason"automatic-wake" | "cron" | "error" | "executing" | "gave-up" | "held" | "idle" | "paused-all" | "paused-one" | "paused-subtree" | "question" | "queue-rule" | "queued-for-slot" | "recovery-wait" | "request" | "retrying" | "stopped-mid-turn" | "ticket-unknown" | "waiting-on-convo" | nullConversationStatus
Where a conversation is now: whether the agent is working, what waits on you, and its latest words.
acceptedInputsnumber Messages accepted that the next turn has not read yet.busybooleanconversationIdstringdeferredboolean The next turn is waiting for its turn to run.deferredBy"account_cap" | "database" | "demand" | "memory" | "net" | "plan_cap" | "priority" | "provider" | "slot" | "user_cap" | "waitlist" | nulldeferredSincenumber | nulletaSecondsnumber | null The measured time left, in seconds, when there is evidence for one.lastAssistantTextstring | null The end of the agent's newest message.nextAttemptAtMsnumber | nullpendingGatesPendingGate[]phaseRunPhaserunStatestringstage"done" | "execute" | "finalise" | "plan" | "review" | nullstateConversationState | nullstatusstring | null The agent's own one-line status, when it set one.titlestringupdatedAtMsnumber Epoch milliseconds.waitingForstring | null What the deferred turn waits on, in plain words.ConversationStatus_eta_estimate_complete
asOfMsoptionalnumber the clock this reading is AS OF: the reader's own for a live read, the held one for a stale copy. A
reader rendering it later says "as of X ago" once it is past STALE_AFTER_MS.basisProjectionBasisconfidenceProjectionConfidencehighMsnumberkind"complete" | "estimate"lowMsnumberprogressAgeMsoptionalnumber active ms since the last evidence (WorkProjection.progressAgeMs).remainingMsnumberrunningLongoptionaltrue an in-flight tick is past its reference, or the work outran its estimate: say it is running long, never present the range as on track.snapshotAgeMsoptionalnumber Derived age of that confirmed copy at the reader's clock; never persisted in storage.ConversationStatus_eta_unknown
asOfMsoptionalnumber the clock this reading is AS OF: the reader's own for a live read, the held one for a stale copy. A
reader rendering it later says "as of X ago" once it is past STALE_AFTER_MS.basis"none"confidence"none"kind"unknown"progressAgeMsoptionalnumber active ms since the last evidence (WorkProjection.progressAgeMs).reasonoptional"no-plan" | "no-progress"runningLongoptionaltrue an in-flight tick is past its reference, or the work outran its estimate: say it is running long, never present the range as on track.snapshotAgeMsoptionalnumber Derived age of that confirmed copy at the reader's clock; never persisted in storage.ConvoBucket
The bucket a row displays in — a SUPERSET of the state: buckets.
needs-you is an is: property rather than a state value: it spans several unrelated runtime
situations (a question, a spent error, a row the machine gave up on), so making it a state:
value would break the rule that every row sits in exactly one State bucket — which group-by
depends on. null is the resting state: a dormant conversation, and done, which is a resting
state rather than a runtime one. Nullable so group-by keeps its "no state" section instead of
inventing a Running bucket for every dormant conversation.
CreateConversationRequest
cwdoptionalstring The working folder the agent starts in. Omit for your default.replyoptional"none" | "optional" | "required" Default optional.streamoptionalboolean Stream the agent's messages as Server-Sent Events instead of one JSON body. Default false.textstring The first message. Up to 100,000 characters.titleoptionalstring A title for the conversation. Omit and Forge names it from the first message.ListConversationsQuery
limitoptionalnumber 1 to 100, default 20.ListMessagesQuery
beforeoptionalstring From the previous page, to read the messages before it. Opaque: pass it back as given.limitoptionalnumber 1 to 1,000, default 50.Message
A message in a conversation: what you (or anyone in your workspace) said, and what the agent said back. Tool activity, thinking and notes are not part of the API.
messageIdstringrole"assistant" | "user"textstringtimestampstring | null ISO 8601, when known.MessagePage
A page of messages, oldest first within the page. The first request returns the newest page; pass
before back to read older ones. limit bounds the transcript entries read and anything that is
not a message (tool activity, notes) is left out, so a page can hold fewer than limit.
beforestring | null Pass as before to read older messages; null when this page reaches the start.conversationIdstringmessagesMessage[]PendingGate
Something waiting on you: a question, an approval or a task.
kindstringpromptstringrequestIdstring | nulltooloptionalstringProjectionBasis
ProjectionConfidence
Reply
One message the agent sent to you.
messageIdstringtextstringtimestampstring ISO 8601.RunPhase
SendMessageRequest
conversationIdstringreplyoptional"none" | "optional" | "required" Default optional.streamoptionalboolean Stream the agent's messages as Server-Sent Events instead of one JSON body. Default false.textstring The message. Up to 100,000 characters.SendResult
conversationIdstringmessageIdstring The id of the message you sent.repliesoptionalReply[] The agent's messages, in order. Absent on a 202 (reply: "none").timedOutoptionalboolean True when the 10-minute wait ran out before the turn ended.