Connect your application.

A domain application plugs into Steepworks as a machine, never as a person. An Account admin issues it a scoped credential. With that credential the application reads the work Steepworks is doing for it, files requests from its own users and follows each one to a result. This page is the contract for that connection.

Work and Requests API · Available. Provisioned per application by an Account admin and in production use. Capability API, operations and application MCP · Planned. Implemented and tested in the repository, switched off by default and not enabled for any customer. Nothing on this page implies a release that has not happened.

Discover the current contract from the server you are talking to. Code in the repository does not prove that a deployed server has an endpoint.

How an application connects

Steepworks records each application a customer owns as an Application inside their Account. The record links the projects that build and improve it, its repository, its deployments and one Operations Project that receives requests. People work on those projects as members. The application itself holds a separate machine credential and is never a member, assignee or approver.

Plane Who runs it What your application does there
Control Steepworks Reads its build and operations work, files requests, follows status and, when enabled, discovers the capabilities granted to it
Identity Steepkey Signs its own users in; Steepworks never proxies application sign-in
Runtime The application and the engines it uses Calls Merrily, Colter or Didist directly with credentials issued by those services; business authorization stays in the application

Steepworks is the connection of record, not the runtime path. Your application's own database stays the system of record for its business, and Steepworks keeps the development and operating relationship, releases, costs and bounded evidence.

Getting a credential

There is no self-serve registration. An Account admin issues the credential from the application's Connections panel in the Steepworks workspace, or a Steepworks operator issues it through the same provisioning authority. Every path runs the same Account authorization and shows the raw token exactly once.

  1. The admin chooses the Application and the scopes it needs from the table below.
  2. Steepworks returns a bearer token once. Move it to the application's secret storage and never place it in source, configuration committed to a repository, a URL or a log.
  3. For request intake the admin also binds an Operations Project. Until that binding exists, creating a request answers 503 integration_not_configured.
  4. To rotate, issue a replacement, verify it, then revoke the old token. A lost token is revoked and replaced; Steepworks stores only a digest and cannot recover it.

Scopes

Scope Grants
work:read Read the work projection for this Application's projects
requests:read List and read the requests this Application has filed
requests:write File requests and post requester replies

A scope is necessary but never sufficient. Every request rechecks that the token is active, that the Application still belongs to the Account and, for intake, that the bound Operations Project still exists. Revocation takes effect on the next request.

Authorization: Bearer <application token>
Content-Type: application/json

Base URL https://api.steepworks.com/api/v1. These routes carry no browser session or CSRF state. An Application token cannot call the user REST routes, the workspace commands or the human MCP endpoint.

Work projection

GET /api/v1/application/work

Returns steepworks.application_work.v2: the Application's active projects, newest first and at most fifty, each with its goal, milestones and the items on its board. It is a read-only, observer-level view. Nothing in it can be changed through this route.

  • Project: id, key, name, status, starts_on, due_on, updated_at, goal, milestones, lane counts and a links.steepworks URL into the project room.
  • Milestone: title, status, builder_status, dates, outcome and accepted_at.
  • Item: kind, ref, title, status, verification_state, confirmation_required, risk, priority and impact, milestone and workstream labels, due_on, the accountable person's label, the performer's label and a deep link.

Labels are display names, never identifiers or email addresses. A status in this projection is Steepworks' record of the work. It is not customer acceptance and not evidence that a release happened.

Requests API

Your application's own users ask for things: a fix, a feature, a question. The Requests API carries each one into the bound Operations Project, where the Steepworks team triages it, promotes it to work and resolves it. Your application polls the public status back and shows it to the requester. Steepworks keeps triage, acceptance, promotion and delivery status; the application keeps the conversation with its user.

Method and path Scope Purpose
POST /application/requests requests:write File a request; 201 on first delivery, 200 on replay
GET /application/requests requests:read List this Application's requests, optionally filtered by ?requester_ref=
GET /application/requests/:id requests:read Read one request with its public status, note and comments
POST /application/requests/:id/comments requests:write Post a reply from the original requester

Filing a request

Send an Idempotency-Key header equal to the body's external_key. Make it a stable key from your own record, 8 to 300 characters of letters, digits, :, ., _ and -, starting with a letter or digit. Resending the same key and body after a timeout returns the original request; a different body under the same key is a conflict.

POST /api/v1/application/requests
Idempotency-Key: yourapp:operator-request:7f3c…

{
  "schema": "steepworks.application_request.create.v1",
  "external_key": "yourapp:operator-request:7f3c…",
  "requester": {"ref": "user:1042", "label": "Front desk"},
  "request": {
    "title": "Recall letters skip patients without email",
    "body": "Steps to reproduce and what we expected…",
    "kind": "issue",
    "workstream": "reliability",
    "source_path": "/console/requests"
  },
  "occurred_at": "2026-10-27T15:04:05Z"
}
  • requester.ref is your stable identifier for the person asking, 3 to 300 characters; label is an optional display name up to 200 characters. Later replies must carry the same ref.
  • request.title is 2 to 400 characters; body is optional Markdown up to 20,000 characters.
  • kind is one of request, question, discussion, issue or feature; it defaults to request.
  • workstream is one of product_experience, reliability, content_data, accessibility or question; it defaults to product_experience.
  • source_path is an optional relative path inside your application where the request came from. Absolute URLs are rejected.
  • occurred_at is an optional ISO-8601 timestamp of when the user asked.

The response wraps the request projection, steepworks.application_request.v1: id, external_key, requester, the request block you sent, public_status, public_note, comments, created_at, updated_at, completed_at and completion_url, with meta.replayed telling you whether this was a replay.

Replying on behalf of the requester

POST /api/v1/application/requests/:id/comments
Idempotency-Key: yourapp:operator-reply:9b21…

{
  "schema": "steepworks.application_request.comment.v1",
  "external_key": "yourapp:operator-reply:9b21…",
  "requester": {"ref": "user:1042", "label": "Front desk"},
  "body": "Also affects the Tuesday batch."
}

The body is 1 to 10,000 characters. A reply whose requester.ref differs from the request's original requester answers 403 requester_mismatch. Comments from the Steepworks side arrive in the request's comments list on your next read.

Request statuses

public_status is a bounded vocabulary your application can render directly. It follows triage first, then the promoted task.

Status Meaning
reviewing Received; the team has not decided yet
needs_details The team asked the requester for more; read public_note
planned Promoted to work that is proposed or ready
in_progress Work has started, or is blocked while it stays in progress
final_checks The work is in review
completed Resolved or done; completed_at and completion_url are set
deferred Kept, but not scheduled
not_planned Declined or canceled, with the reason in public_note

Poll rather than wait for a callback. Steepworks does not yet deliver signed events to applications, so a request your application has already created should be re-read with GET, never re-created. Keep the last known status if a read fails.

Errors

Every error is {"error": {"code": "…", "message": "…"}}.

HTTP Code Cause
400 invalid_idempotency_key Header missing, repeated or outside the allowed pattern
400 idempotency_key_mismatch external_key differs from the header
401 unauthorized Missing, revoked or unknown bearer token
403 forbidden The token lacks the scope for this route
403 requester_mismatch A reply from someone other than the original requester
404 not_found No such request for this Application
409 idempotency_conflict Same key, different content
422 unsupported_schema, invalid_source_path, invalid_request Wrong schema name, absolute source path or a field outside its bounds
503 integration_not_configured No Operations Project is bound for intake

Capability API

Planned. Implemented and tested in the repository, disabled by default and not enabled for any customer. The contract below is what will be switched on, not an endpoint you can call today.

Beyond build work, Steepworks will let an application discover which shared services its Account has granted it and read bounded, source-backed facts from them. The first capabilities are a connection read and two reads from a linked Merrily customer workspace. Neither communicates with a customer, approves an action, charges usage or runs a workflow.

Setup chain

An Account admin or a Steepworks operator provisions the chain in order, and each step records a version: register the application privately within the Account, install it for one environment, grant each capability, bind each resource (for Merrily, only after the reviewed two-sided account link is accepted), activate the installation and issue a credential. Suspension blocks reads; disconnect is terminal.

Capability credentials are separate from Application tokens, expire within 90 days and carry their own scopes: capabilities:read, connection:read, merrily:readiness and merrily:context.read. Every request also names its environment, and installation, header and deployment environment must agree.

Authorization: Bearer <capability token>
X-Steepworks-Environment: production
Request Scope Returns
GET /application/capabilities capabilities:read steepworks.capabilities.v1: the capabilities this installation may call, with readiness rechecked on each call
GET /application/connection connection:read steepworks.connection.v1: installation ID, environment, app key, name, revision and capability version
GET /application/merrily/readiness merrily:readiness steepworks.merrily.readiness.v1: the linked customer and limited readiness checks
GET /application/merrily/contacts/:contact_id/context merrily:context.read steepworks.merrily.contact_context.v1: one contact and up to 20 source-backed facts with provenance, marked incomplete where coverage ends

None of these routes accepts query parameters, and a supplied Account or installation ID is rejected rather than trusted. Responses carry Cache-Control: no-store. Errors use the same envelope as above: 401 unauthorized for an invalid, expired or inactive identity or a wrong environment, 403 forbidden for a missing scope, grant or binding, 422 invalid_arguments for unexpected input and 404 not_found while the API is disabled.

Durable operations

Planned. Switched on separately from the capability API and off by default. The first contract admits only read operations.

An operation is a capability call Steepworks runs for you with a receipt: admitted under the Account, dispatched by a worker, observed and kept. Your application submits it, polls the receipt and may cancel before dispatch. It needs operations:submit and operations:read, optionally operations:cancel, plus the scope of the underlying read.

HTTP Application MCP tool
POST /application/operations steepworks_operations_submit
GET /application/operations/:id steepworks_operations_get
POST /application/operations/:id/cancel steepworks_operations_cancel
{
  "capability": "merrily.readiness",
  "contract_version": 1,
  "idempotency_key": "readiness-check-001",
  "input": {}
}

Submission answers 202 with steepworks.operation.v1: a stable id, status, version, cancellation flag, observation revision, bounded result or error and UTC timestamps. Polling returns the same shape with 200. Cancellation takes the receipt's expected_version. Statuses are queued, dispatching, succeeded, failed, canceled and uncertain. A successful readiness read may still report ready: false.

Replay is keyed by Account, installation, environment, capability, contract version and your key; the same key with different input answers 409 idempotency_conflict. Each installation may hold 100 open operations; beyond that, 429 rate_limited. Input is bounded to 4 KiB and results to 8 KiB. No usage charge is inferred from an operation.

Application MCP

Planned. Served only when the capability API is enabled.

POST https://api.steepworks.com/api/v1/application/mcp

Agents running inside your application can use the same capability credential over MCP, with the same bearer token and X-Steepworks-Environment header as REST. tools/list needs capabilities:read and returns only the reads this installation is admitted to. tools/call rechecks scope, grant, binding and the remote service on every call.

Tool Purpose
steepworks_connection_read This installation's identity and environment
steepworks_merrily_readiness Readiness of the linked Merrily workspace, when granted
steepworks_merrily_contact_context_read Bounded context for one contact_id, when granted
steepworks_operations_submit, steepworks_operations_get, steepworks_operations_cancel The durable operation protocol above

This endpoint is distinct from the human MCP endpoint documented for agents. A capability credential cannot call /api/v1/mcp or any workspace command, and a user credential cannot call this one.

What the connection never does

  • It does not act as a person. No scope lets an application create tasks, accept work, approve spending or release software. A request becomes work only when the Steepworks team promotes it.
  • It does not proxy your runtime. Customer records, commerce and hosted agents are called directly on Merrily, Didist and Colter with credentials those services issue.
  • It does not hold your users' identity. Sign-in to your application is Steepkey's or your own; Steepworks sees requester labels, not accounts.
  • Its status is a record, not proof. A completed request or a done item says Steepworks recorded the result. Acceptance, release and payment are decided by named people and kept separately.
  • It does not push. There are no signed callbacks yet; your application polls.

What is planned

These are direction, not commitments with dates. Each becomes available only after it is verified end to end and this page says so.

  • Enabling the capability API, durable operations and application MCP for a first customer.
  • Grants beyond Merrily reads: Didist, Colter and other engine capabilities.
  • An OpenAPI description and client libraries for the Application routes.
  • A Connections view inside the workspace that shows every active credential and grant.
  • Signed event delivery to applications in place of polling.
  • Self-serve registration for application developers under an Account admin's approval.

Credentials and security

  • Tokens are random, shown once and stored only as a digest. Steepworks cannot read them back; losing one means revoke and replace.
  • Supply tokens through the environment or a secret store, never on a command line, in a URL, in a repository file or in a log.
  • Account admins list and revoke Application tokens from the application's Connections panel. Revocation takes effect on the next request.
  • Capability credentials expire within 90 days; rotate by issuing, verifying, then revoking.
  • Use HTTPS everywhere outside loopback development. Capability routes answer Cache-Control: no-store.
  • Application credentials never enter user routes, and user credentials never enter application routes. Keep them in separate secrets with separate owners.

Have an application to connect?

Start with what the application should do for your business. We set up the Account, the Application record and the first credential with you.

Start with a goal