API DSL Reference
1. Overview
Section titled “1. Overview”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:
@apiand may define one or more APIs.
2. API Definition
Section titled “2. API Definition”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) : OrderEquivalent explicit style:
@api
OrderAPI style:rest get /orders/{id} getOrder(id:String) : OrderThe syntax of individual operations depends on the API style.
2.1 API-Level Attributes
Section titled “2.1 API-Level Attributes”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).
2.2 API Composition
Section titled “2.2 API Composition”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() : Stringinclude 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.
Overrides
Section titled “Overrides”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) : OrderAn 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.
3. REST
Section titled “3. REST”REST is the default API style.
3.1 Syntax
Section titled “3.1 Syntax”<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.
3.2 REST Endpoint Elements
Section titled “3.2 REST Endpoint Elements”| 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 _.
3.3 Path Parameters
Section titled “3.3 Path Parameters”REST paths may contain parameters.
Example:
get /orders/{id} getOrder(id:String) : OrderEvery 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.
3.4 Query Parameters
Section titled “3.4 Query Parameters”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,) : OrderPagePath 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,) : AuditActionPagein-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.
Query Parameter Rules
Section titled “Query Parameter Rules”in-queryis 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-contextare not query parameters. - Query parameters currently use scalar Ocean types (
String,Int,Float,Double,Boolean,Date,Time,DateTime, andTimestamp) or enums. Collection and object query encodings require an explicit future contract. GETandDELETEendpoints still cannot declare@request;in-querydoes 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.
Audit Filter Example
Section titled “Audit Filter Example”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, ) : AuditActionPage3.5 Payload Representations
Section titled “3.5 Payload Representations”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) : OrderResponsepost /orders createOrder(req:OrderRequest) : OrderResponse @request:application/jsonpost /orders createOrder(req:OrderRequest) : OrderResponse @request:json @response:xmlput /orders updateOrder(req:OrderRequest) : OrderResponse @request:application/xml @response:application/xmlpost /upload upload(file:UploadRequest) : UploadResult @request:multipartpost /login login(req:LoginRequest) : LoginResponse @request:formPayload Representation Rules
Section titled “Payload Representation Rules”- Request and response representations are configured independently.
GETandDELETEendpoints cannot declare@request.POST,PUT, andPATCHdefault toapplication/jsonwhen@requestis omitted.- Responses default to
application/jsonwhen@responseis omitted. - Payload aliases are normalized to their canonical media types.
3.6 Empty Input and Output
Section titled “3.6 Empty Input and Output”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) : _3.7 CORS Configuration
Section titled “3.7 CORS Configuration”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>CORS Fields
Section titled “CORS Fields”| 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 Rules
Section titled “CORS Rules”- CORS applies at API level rather than per endpoint.
- When
allowCredentialsistrue,allowOriginsmust not contain*. - REST APIs should allow
OPTIONSwhen 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(_) : _3.8 Context-Derived Inputs
Section titled “3.8 Context-Derived Inputs”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:
# Sessionpost /auth/session getSession(input:SessionInput) : *SessionResultget /auth/session getSessionWithCtxToken(_) : *SessionResult @from-context:tokenContext-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.
4. gRPC
Section titled “4. gRPC”An API may use the gRPC style.
4.1 Syntax
Section titled “4.1 Syntax”<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(_) : _4.2 Elements
Section titled “4.2 Elements”| 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. |
gRPC Rules
Section titled “gRPC Rules”- 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:truewhere supported. - gRPC path inference is based on
ApiName.MethodName.
5. GraphQL
Section titled “5. GraphQL”An API may use the GraphQL style.
5.1 Syntax
Section titled “5.1 Syntax”<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) : Product5.2 Operations
Section titled “5.2 Operations”| Operation | Description |
|---|---|
query |
Defines a GraphQL read operation. |
mutation |
Defines a GraphQL write or state-changing operation. |
GraphQL Rules
Section titled “GraphQL Rules”- 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.
6. WebSocket
Section titled “6. WebSocket”An API may use the WebSocket style for streaming or bidirectional communication.
6.1 Syntax
Section titled “6.1 Syntax”<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) : OrderUpdate6.2 Elements
Section titled “6.2 Elements”| 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. |
Suggested Modes
Section titled “Suggested Modes”| 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. |
WebSocket Rules
Section titled “WebSocket Rules”- 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.
7. SOAP
Section titled “7. SOAP”An API may use the SOAP style for XML-based messaging and contract-driven services.
7.1 Syntax
Section titled “7.1 Syntax”<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) : _7.2 Elements
Section titled “7.2 Elements”| 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 Rules
Section titled “SOAP Rules”- 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.
8. API Operation References
Section titled “8. API Operation References”API operations are referenced using their fully qualified name:
<ApiName>.<MethodName>Examples:
OrderAPI.createOrderUserAPI.getUserChatAPI.connectToChatFully qualified operation references allow API methods to be referenced by other DSL constructs such as:
@fsm;@component;@integration;@service.
9. Imports
Section titled “9. Imports”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) : ResponseThe 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.
10. Rules and Constraints
Section titled “10. Rules and Constraints”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.
includecomposes 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.
11. Complete REST Example
Section titled “11. Complete REST Example”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.
12. Related Knowledge
Section titled “12. Related Knowledge”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.