A business process API should help a client understand work that may take longer than a single connection. The API needs to distinguish accepting a request from completing its outcome, explain how the client can observe progress, and give operators a way to resolve uncertainty after interruption. Naming a few endpoints is only the beginning.
Consider a fictional document intake service. A client submits references to a package, the system validates and processes its contents, and a reviewer may approve the result before publication. The design below is a reference pattern for that kind of service, not an assertion that ProcessAPI.com operates a hosted API. The purpose is to make implementation choices concrete enough to review and test.
Start with domain objects and outcomes
Identify the object the business recognizes, such as a document package, and separate it from an execution run. A package can have several runs as inputs or processing rules change. A run represents one accepted attempt to process a particular version under a particular configuration.
Give each object a stable identity. Avoid making a run's identity depend on a worker name, a queue position, or a temporary storage path. Those details can change without changing the accepted business request. Keep them as supporting execution metadata instead.
Write down the outcome that matters to the client. In the example, processing is complete only when the required artifacts and validation summary exist. Publication is a separate business transition if it requires approval. This prevents a client from interpreting a finished extraction job as permission to use an unreviewed result.
Define the asynchronous acceptance contract
A submission endpoint should validate what it can before accepting work: required fields, authorization, supported process versions, and basic input references. The response should make clear whether the work was accepted and provide the identity needed to observe it.
In this reference design, an accepted submission returns an HTTP 202 response with a run identifier and status location. That is a design choice, not a guarantee that processing has started or will succeed. The response body should use language consistent with that distinction.
Document rejection separately. A malformed request should receive a useful validation error rather than enter a queue destined to fail. Avoid returning a successful-looking run object for an operation the service has not actually accepted unless the contract explicitly defines and explains that behavior.
Make the contract machine-readable
The OpenAPI 3.1.1 specification defines a language-independent description format for HTTP APIs, including operations, parameters, schemas, and responses. A written contract can support review and tooling, but it does not implement the service or prove that the running system follows it.
Describe the example's submission, status, and result operations with explicit request and response schemas. Include meaningful examples for pending, completed, and failed runs. Document authentication requirements and each operation's possible errors alongside the successful response.
Keep examples consistent with the actual field names and permitted states. A beautifully rendered reference becomes harmful when its examples describe a different version than the schema. Treat contract changes as reviewable code changes and test the implementation against the accepted description.
Separate lifecycle state from progress detail
Choose a small set of run states with documented transitions. This reference pattern uses queued, running, awaiting review, succeeded, failed, and canceled. Progress details can describe item counts and current stages without multiplying the number of lifecycle states.
A completed worker action is not necessarily a completed run. If some required items remain unresolved, the run should reflect the agreed partial-success policy. Define whether the API allows a partial result, waits for repair, or ends with a failed state and available item-level outcomes.
Document terminal behavior. Can a succeeded run ever change, or must a correction create another run? In this example, accepted run outputs are immutable and a changed interpretation creates a new run. That makes status observation easier to reason about and gives clients a stable reference for historical results.
Design idempotency around client intent
Let clients identify a repeated submission that represents the same intended operation. Scope the idempotency key to an appropriate account and operation, and specify how long its association is retained. Reusing a key with materially different request content should not silently create an unrelated run.
Preserve the accepted response for retries where the design supports it. A client whose connection failed after acceptance needs a way to recover the same run identity. The guarantee must be backed by durable coordination, not an in-memory dictionary that disappears when the API restarts.
Also distinguish submission idempotency from downstream safety. Preventing two run records does not automatically prevent a worker from publishing a result twice after an interrupted dependency call. The reliability playbook examines that separate boundary and the need for reconciliation.
Authorize objects, not just endpoints
Authentication identifies the caller. Authorization determines whether that caller can submit work, read a particular run, download its outputs, or approve publication. Apply object-level checks wherever an identifier selects data, including status and result routes.
Do not assume that a hard-to-guess run identifier is an access control. The same authorization boundary should apply when a result is delivered through a signed storage link or a webhook. Define expiration and access scope for any delegated artifact access.
Separate operational roles where the business requires it. A worker may create extraction results without being allowed to approve them. An observer may read run status without seeing the underlying documents. Model those requirements in the contract rather than forcing every user through one broad administrative credential.
Provide errors that support recovery
Return stable error codes for conditions a client or operator can act on. Distinguish an invalid input, an unavailable dependency, a denied operation, and an exhausted retry policy. Include a correlation identifier without exposing secrets or unnecessary source content.
Explain whether an error is terminal for the run and what kind of action can repair it. A client should not have to infer from an English sentence whether it should retry a submission, correct a document, or wait for an operator. Keep the detail useful, but do not promise that every dependency failure has an immediate automatic solution.
For item-level failures, preserve the relationship to the original manifest. A batch with several failed documents needs more than one generic run error. Return a bounded summary and a structured result reference so clients can reconcile outcomes without receiving an enormous status payload.
Version the process as well as the interface
An API version and a process version serve different purposes. The interface can remain stable while an extraction policy or approval rule changes. Record the accepted process version with each run so a historical result remains explainable after the business workflow evolves.
Decide which changes are compatible for clients. Adding an optional field may be easier to accommodate than changing the meaning of an existing state. Document unknown-field and unknown-enum handling rather than assuming every consumer will behave generously.
Test the complete client journey: submit, recover after an uncertain response, observe, handle failure, and retrieve the accepted artifacts. The reference documentation provides a compact job contract and sample manifest to review. These examples are most useful when treated as a starting point for your own requirements, not a universal prescription.
Conclusion: clarity is the core API feature
A useful business process API makes accepted intent, execution state, authorization, and business outcome distinguishable. Design the contract so clients can recover after interruption and operators can explain unfinished work. Endpoints should express that agreement clearly; they should not conceal the lifecycle decisions that determine whether the system is dependable.



