Skip to content
Ocean-Atlasv0.1.0Canonical Knowledge

API DSL Reference

The @api section defines the public interface of a service.

It describes how external clients interact with a service through well-defined operations using typed request and response objects.

The Ocean API model is technology-independent. An API declares a style that determines the syntax and interaction model of its operations.

Supported styles include:

  • REST — default;
  • gRPC;
  • GraphQL;
  • WebSocket;
  • SOAP.

A file begins with:

@api

and may define one or more APIs.


General syntax:

@api
<ApiName> [style:<style>]
<style-specific definitions>

If no style is specified, REST is used by default.

Example:

@api
OrderAPI
get /orders/{id} getOrder(id:String) : Order

Equivalent explicit style:

@api
OrderAPI style:rest
get /orders/{id} getOrder(id:String) : Order

The syntax of individual operations depends on the API style.

Before its operations, an API may declare attributes as key = value lines, one per line, indented under the API name:

TodoApi style: rest
engine = gin
configType = ApiConfig
tags = external
version = 1.0.0
description = ToDo API Description
basePath = /
generateSwagger = true
get /todo/item/{id} getItem(id:String) : TodoItem
Attribute Required Description
engine Yes Transport/framework that serves the API, such as gin for REST.
configType Yes Datatype that supplies the API’s runtime configuration (see dsl.config).
version No API version string, typically semantic (1.0.0).
basePath No Path prefix prepended to every operation path. Defaults to /.
description No Human-readable API description, surfaced in generated documentation.
tags No Comma-separated classification tags, such as external, internal.
generateSwagger No Whether an OpenAPI/Swagger document is generated for the API. Defaults to false.

Whitespace around = is not significant, and style: may be written with or without a space after the colon (style:rest or style: rest).


An API may compose the public operations of one or more other APIs. Composition is a contract-level capability: it reuses operation definitions without repeating them in the composing API. It does not declare runtime routing; a @service gateway declares how the public API is implemented.

AnswerGatewayApi style:rest
engine = gin
configType = ApiConfig
basePath = /answers
generateSwagger = true
include TimeDateApi, CalendarApi
get /zone-time getZoneTime() : String

include accepts one or more comma-separated API names. Inside an @api definition, it always means API composition. It is distinct from the existing repository-level @include directive. Included APIs may include other APIs, so a composed API exposes the transitive effective set of operations. Every included API must use the same API style as the composing API.

The composing API owns its transport-level configuration: engine, configType, basePath, CORS, generated documentation, and other API-level attributes are taken only from the composing API. Included APIs contribute operations, not their basePath or API-level attributes. For REST, an included operation keeps its method and relative path, and the composing API’s basePath is applied when it is exposed.

A composing API may declare an operation with the same method name as an included operation. The local declaration overrides the inherited operation:

PublicOrdersApi style:rest
basePath = /public/orders
include api InternalOrdersApi
# Exposes the inherited getOrder contract at a public route.
get /{id} getOrder(id:String) : Order

An override must keep the inherited operation contract compatible: the input names and types, output type, and context-derived inputs must match. It may change transport-specific presentation and documentation. For REST, this includes the HTTP method, path, payload representations, and endpoint configuration.

If two included APIs provide the same operation name, the composition is ambiguous and invalid unless the composing API declares one compatible local override. API inclusion cycles are invalid. An API’s final effective operation set must contain unique operation names.

Existing APIs without include api keep their current behavior unchanged.


REST is the default API style.

<ApiName> [style:rest]
<method> <path> <MethodName>(<inputName>:<InputType> [in-query],...) : <OutputType> [@request:<payload-type>] [@response:<payload-type>] [@from-context:<item1>,<item2>,...] [with <config>]

An endpoint may be written on one line or, for readability, with its input parameters on separate indented lines.

Example:

TodoApi style: rest
engine = gin
configType = ApiConfig
tags = external
version = 1.0.0
description = ToDo API Description
basePath = /
generateSwagger = true
get /todo/info getInfo(_) : String
get /todo/items/{offset}/{limit} listItems(offset:Int, limit:Int) : List<TodoItem>
get /todo/item/{id} getItem(_) : TodoItem
get /todo/item2/{id} getItem2(_) : TodoItem
get /todo/title/{title} findItemByTitle(title:String) : List<TodoItem>
get /todo/title-and-priority/{title}/{priority} findItemByTitleAndPriority(title:String, priority:Priority) : List<TodoItem>
get /todo/title-or-priority/{title}/{priority} findItemByTitleOrPriority(title:String, priority:Priority) : List<TodoItem>
post /todo/item createItem(item:TodoItem) : TodoItem
put /todo/item adjustItem(item:TodoItem) : TodoItem
delete /todo/item/{id} deleteItem(_) : _

All id path parameters are String by default when no explicit type is declared.


Element Description
method HTTP method such as get, post, put, patch, or delete.
path URL path. Supports path parameters such as {id} or typed placeholders where supported.
MethodName Unique operation identifier used to reference the API operation.
InputType Datatype used as request input. _ indicates no input.
in-query Optional explicit binding of an input parameter to the URL query string.
OutputType Datatype returned by the operation. _ indicates no output.
@request Optional request payload representation.
@response Optional response payload representation.
@from-context Optional values provided implicitly from the execution context.
with Optional comma-separated key:value endpoint configuration, such as auth:required, version:v1.

HTTP methods are written in lowercase.

Paths are written in lowercase. Path placeholders may be untyped ({id}) or typed ({id:String}); an untyped placeholder defaults to String.

Method names follow Ocean field naming conventions: they begin with a lowercase letter and contain only letters, digits, and _.

Input and output type names follow Ocean datatype naming conventions: they begin with an uppercase letter and contain only letters, digits, and _.


REST paths may contain parameters.

Example:

get /orders/{id} getOrder(id:String) : Order

Every path parameter must also appear in the method input list, and its declared type there applies to the path placeholder.

Path binding is implicit: an input whose name matches a placeholder in the path is a path parameter. Do not add in-query to a path parameter.

REST endpoints may bind an input parameter to the URL query string by adding in-query after its type:

get /orders searchOrders(
status : *OrderStatus in-query,
cursor : *String in-query,
limit : *Int in-query,
) : OrderPage

Path and query parameters may be combined in the same endpoint. Parameters matching a path placeholder bind to the path; only the remaining filter and pagination parameters use in-query:

get /tenants/{tenantId}/audit/actions listAuditActions(
tenantId : String,
actorId : *String in-query,
action : *String in-query,
cursor : *String in-query,
limit : *Int in-query,
) : AuditActionPage

in-query is explicit by design. On GET and DELETE endpoints, every input declared in the signature must therefore be either a path parameter or be marked in-query. This prevents an input from silently acquiring an unintended HTTP binding.

Query parameters are also allowed on POST, PUT, and PATCH endpoints when an operation has query-based options in addition to its request payload. Inputs without in-query retain their existing request-body behavior for those methods.

The parameter name is the query-string key. An optional Ocean type, such as *String, *Int, or *DateTime, represents an optional query parameter; a non-optional type represents a required query parameter.

The path must not contain a literal query string. Write /orders, not /orders?status=...; all query parameters belong in the typed method signature.

  • in-query is valid only for REST endpoint inputs.
  • A query parameter must not also be a path parameter.
  • A parameter may be bound at most once.
  • Context-derived inputs declared with @from-context are not query parameters.
  • Query parameters currently use scalar Ocean types (String, Int, Float, Double, Boolean, Date, Time, DateTime, and Timestamp) or enums. Collection and object query encodings require an explicit future contract.
  • GET and DELETE endpoints still cannot declare @request; in-query does not create a request body.
  • Existing REST definitions remain unchanged: path placeholders continue to define path parameters, and request-body inputs retain their current behavior.
AuditApi style:rest
engine = gin
configType = ApiConfig
basePath = /audit
get /actions listAuditActions(
tenantId : *String in-query,
actorId : *String in-query,
sourceService : *String in-query,
targetType : *String in-query,
targetId : *String in-query,
action : *String in-query,
result : *String in-query,
from : *DateTime in-query,
to : *DateTime in-query,
cursor : *String in-query,
limit : *Int in-query,
) : AuditActionPage

REST endpoints may explicitly define request and response payload representations.

Supported representations are:

Alias Canonical Media Type Request Response
json application/json Yes Yes
xml application/xml Yes Yes
multipart multipart/form-data Yes No
form application/x-www-form-urlencoded Yes No

Both aliases and canonical media types are accepted.

Examples:

post /orders createOrder(req:OrderRequest) : OrderResponse
post /orders createOrder(req:OrderRequest) : OrderResponse @request:application/json
post /orders createOrder(req:OrderRequest) : OrderResponse @request:json @response:xml
put /orders updateOrder(req:OrderRequest) : OrderResponse @request:application/xml @response:application/xml
post /upload upload(file:UploadRequest) : UploadResult @request:multipart
post /login login(req:LoginRequest) : LoginResponse @request:form
  • Request and response representations are configured independently.
  • GET and DELETE endpoints cannot declare @request.
  • POST, PUT, and PATCH default to application/json when @request is omitted.
  • Responses default to application/json when @response is omitted.
  • Payload aliases are normalized to their canonical media types.

Use _ when an endpoint has no input or no output.

No input — either (_) or an empty parameter list ():

delete /orders/{id} deleteOrder(_) : _
get /orders getAllOrders() : List<Order>

No output:

put /orders/{id} updateOrder(req:UpdateOrderRequest) : _

An API may define Cross-Origin Resource Sharing configuration using cors:.

CORS controls browser access to an API from different origins, such as a UI application hosted on another domain or port.

Syntax:

<ApiName> [style:<style>]
cors:
allowOrigins: <origin>[, <origin>, ...]
allowMethods: <method>[, <method>, ...]
allowHeaders: <header>[, <header>, ...]
allowCredentials: <true|false>
Field Required Description
allowOrigins Yes Allowed origins including scheme, host, and optional port.
allowMethods No Allowed HTTP methods. Defaults to GET, POST, PUT, DELETE, OPTIONS.
allowHeaders No Allowed request headers. Defaults to Content-Type, Authorization.
allowCredentials No Whether browser credentials are allowed. Defaults to false.
  • CORS applies at API level rather than per endpoint.
  • When allowCredentials is true, allowOrigins must not contain *.
  • REST APIs should allow OPTIONS when browser preflight requests are required.
  • If CORS configuration is omitted, no CORS headers are generated.

Example:

@api
GatewayAPI style:rest
basePath = /
cors:
allowOrigins: http://localhost:5173, https://ui.ocean-lab.ai
allowMethods: GET, POST, PUT, DELETE, OPTIONS
allowHeaders: Content-Type, Authorization
allowCredentials: true
post /auth/login login(req:LoginRequest) : LoginResponse
post /auth/logout logout(_) : _

REST endpoints may declare values supplied implicitly by the execution context using @from-context.

Syntax:

<method> <path> <MethodName>(<inputs>) : <OutputType> @from-context:<item1>,<item2>,...

Example:

# Session
post /auth/session getSession(input:SessionInput) : *SessionResult
get /auth/session getSessionWithCtxToken(_) : *SessionResult @from-context:token

Context-derived items are not part of the explicit API input signature.

They represent environmental or execution information such as:

  • authentication tokens;
  • request IDs;
  • tracing metadata.

The transport layer extracts these values and makes them available to the service execution context before invoking service logic.

Validation may be enforced by generated code or runtime infrastructure.


An API may use the gRPC style.

<ApiName> style:grpc
rpc <MethodName>(<InputType>) : <OutputType>

Example:

UserAPI style:grpc
rpc registerUser(r:RegisterUserRequest) : UserResponse
rpc getUser(r:GetUserRequest) : User
rpc updateProfile(r:UpdateProfileRequest) : _
rpc deleteAccount(_) : _
Element Description
rpc Declares a gRPC operation.
MethodName Unique operation identifier.
InputType Request datatype. _ indicates no input.
OutputType Response datatype. _ indicates no output.
config Optional comma-separated key:value operation configuration, such as stream:true.
  • Each method name must be unique within its API.
  • _ may indicate no input or no output.
  • Methods are unary by default.
  • Streaming configuration may use with stream:true where supported.
  • gRPC path inference is based on ApiName.MethodName.

An API may use the GraphQL style.

<ApiName> style:graphql
query <name>(<params>) : <ReturnType>
mutation <name>(<params>) : <ReturnType>

Example:

ProductAPI style:graphql
query getProduct(id: String) : Product
query listProducts(category: String) : List<Product>
mutation createProduct(input: ProductInput) : Product
mutation updatePrice(id: String, price: Float) : Product
Operation Description
query Defines a GraphQL read operation.
mutation Defines a GraphQL write or state-changing operation.
  • Every GraphQL query or mutation must define a return type.
  • Parameters are named and typed.
  • Operation and parameter names follow Ocean field naming conventions.
  • Parameter and output type names follow Ocean datatype naming conventions.
  • GraphQL operations cannot use _ as the output type.
  • List<Type> represents list results.
  • Input validation and resolver contracts are derived from parameter and output datatypes.

An API may use the WebSocket style for streaming or bidirectional communication.

<ApiName> style:websocket
ws <path> <MethodName>(<inputName>:<InputType>, ...) : <OutputType> [with <config>]

Example:

ChatAPI style:websocket
ws /chat/connect connectToChat(ChatInit) : ChatEvent
ws /notifications listenForAlerts(_) : AlertEvent with mode:subscribe
ws /orders/live getOrderUpdates(OrderFilter) : OrderUpdate
Element Description
ws Declares a WebSocket or streaming endpoint.
path Lowercase WebSocket endpoint path; supports placeholders such as {id} and {id:String}.
MethodName Unique operation identifier.
InputType Datatype used when initiating or interacting with the connection. _ indicates no input.
OutputType Datatype streamed from the server.
config Optional comma-separated key:value WebSocket configuration.
Mode Description
subscribe Server sends events after the initial connection or subscription.
rpc Request-response interaction over WebSocket.
chat Full-duplex communication.
log Continuous stream of logs or updates.
  • Input may be _ when no initial message is required.
  • Output type must be provided.
  • Stream behavior may be configured using with mode:<value> where supported.

An API may use the SOAP style for XML-based messaging and contract-driven services.

<ApiName> style:soap
operation <MethodName>(<InputType>) : <OutputType> [with <config>]

Example:

BillingAPI style:soap
operation createInvoice(req:CreateInvoiceRequest) : InvoiceResponse
operation getInvoice(req:GetInvoiceRequest) : Invoice
operation cancelInvoice(req:CancelInvoiceRequest) : _
Element Description
operation Declares a SOAP operation.
MethodName Unique operation identifier.
InputType Request datatype. _ indicates no input.
OutputType Response datatype. _ indicates no output.
config Optional SOAP-specific configuration.
  • SOAP operations are contract-based and typically map to WSDL definitions.
  • Input and output types are serialized as XML.
  • _ may indicate no input or no output.
  • Operation names must be unique within the API.
  • Additional SOAP configuration (such as namespaces or bindings) may be provided via with.

API operations are referenced using their fully qualified name:

<ApiName>.<MethodName>

Examples:

OrderAPI.createOrder
UserAPI.getUser
ChatAPI.connectToChat

Fully qualified operation references allow API methods to be referenced by other DSL constructs such as:

  • @fsm;
  • @component;
  • @integration;
  • @service.

Only datatypes may be imported into an @api file from the Ocean Repository.

Imported datatypes may be used as:

  • request types;
  • response types;
  • operation parameters.

Example:

@api
@import datatype O.domain.payment.CardInfo@1.2.0 as CardInfo
PaymentAPI
post /cards addCard(cardInfo: CardInfo) : Response

The alias is required and is used in API method signatures. Other definition kinds cannot be introduced with @import in an @api file.

Reusable definitions may also be made available through the supported Ocean include mechanism.


The following general rules apply:

  • An API file starts with @api.
  • A file may define one or more APIs.
  • REST is the default style.
  • API operation syntax depends on the selected style.
  • Operations may be written on one line or with input parameters on separate indented lines.
  • include composes the effective operations of existing APIs. Included APIs may themselves include APIs; every included API must use the same style, and inclusion cycles are invalid.
  • Operation names must be unique in an API’s effective operation set. A local compatible operation may override an inherited operation with the same name.
  • Input and output types use Ocean datatypes.
  • _ represents no input or no output where supported by the API style.
  • API operations are referenced using <ApiName>.<MethodName>.
  • Datatypes may be imported from the Ocean Repository.
  • Style-specific rules apply in addition to these general rules.

The following is a complete @api file (ocean-examples/0008-invoice-approval-system/40-api.ocn):

@api
InvoiceApi style:rest
engine = gin
configType = ApiConfig
version = 1.0.0
generateSwagger = true
# -------------------------
# Invoice
# -------------------------
get /invoice/{id} getInvoice(id:String) : *Invoice
get /invoices getAllInvoices() : List<*InvoiceSummary>
get /invoices/{offset}/{limit} getInvoices(offset:Int, limit:Int) : List<*Invoice>
#get /invoices/pending/{userId} getPendingInvoices(userId:String) : List<*Invoice>
post /invoice/submit submitInvoice(req:*SubmitInvoiceReq) : *Invoice
post /invoice/update updateInvoice(item: *Invoice) : *Invoice
post /invoice/{id}/approve approveInvoice(req:ApproveInvoiceReq) : *Invoice
post /invoice/{id}/reject rejectInvoice(req:RejectInvoiceReq) : Invoice
delete /invoice/{id}/delete deleteInvoice(id:String) : _
get /invoice/find-by-status/{status} findInvoiceByStatus(status: InvoiceStatus) : List<*Invoice>
get /invoice/find-by-customer/{customerId} findInvoiceByCustomer(customerId: String) : List<*Invoice>
get /invoice/find-by-created-by/{createdById} findInvoiceByCreatedBy(createdById: String) : List<*Invoice>
get /invoice/find-by-approved-by/{approvedById} findInvoiceByApprovedBy(approvedById: String) : List<*Invoice>
get /invoice/find-by-status-and-customer/{status}/{id} findInvoiceByStatusAndCustomer(status: InvoiceStatus, id : String) : List<*Invoice>
# -------------------------
# User
# -------------------------
get /user/{id} getUser(id:String) : *User
get /users getAllUsers() : List<User>
get /find-user-by-name/{name} findUserByName(name:String) : *User
get /find-user-by-role/{role} findUserByRole(role:String) : List<*User>
get /users/{offset}/{limit} getUsers(offset:Int, limit:Int) : List<*User>
post /user/create createUser(user:User) : *User
post /user/update updateUser(user:User) : *User
delete /user/{id} deleteUser(id:String) : _
# -------------------------
# Customer
# -------------------------
get /customer/{id} getCustomer(id:String) : *Customer
get /customers getAllCustomers() : List<Customer>
get /find-customer-by-name/{name} findCustomerByName(name:String) : *Customer
get /find-customer-by-department/{department} findCustomerByDepartment(department:String) : List<*Customer>
get /customers/{offset}/{limit} getCustomers(offset:Int, limit:Int) : List<*Customer>
post /customer/create createCustomer(customer:Customer) : *Customer
post /customer/update updateCustomer(customer:Customer) : *Customer
delete /customer/{id} deleteCustomer(id:String) : _

This example demonstrates:

  • explicit REST style;
  • API-level attributes (engine, configType, version, generateSwagger);
  • several resources (Invoice, User, Customer) grouped in one API with comment banners;
  • a commented-out endpoint;
  • path parameters and typed parameters (offset:Int, status:InvoiceStatus);
  • empty parameter lists (getAllInvoices()) for no input;
  • pointer request and response types (*Invoice, req:*SubmitInvoiceReq, List<*Invoice>);
  • list responses;
  • _ as an empty output type.

The @api DSL is related to:

  • dsl.datatype — defines datatypes used by API inputs, outputs, and parameters.
  • dsl.context — defines context data that may be supplied implicitly through @from-context.
  • dsl.import — defines the mechanism for importing selected datatype definitions from the Ocean Repository.
  • dsl.include — defines the mechanism for including reusable definitions from the Ocean Repository.

These semantic relationships are declared in the document metadata.