A REST channel connects an incoming HTTP request to one of your services. When a client calls your API endpoint, Zato routes the request to the service you specified, passes along any parameters, and returns the service's response.
In Dashboard, go to Connections → Channels → REST and click Create:

The key fields:
/api/customersThe most common way to handle REST requests is with data models. Define your request and response as Python dataclasses, and Zato handles JSON parsing and serialization automatically:
# -*- coding: utf-8 -*-
# stdlib
from dataclasses import dataclass
# Zato
from zato.server.service import Model, Service
@dataclass(init=False)
class CreateOrderRequest(Model):
customer_id: str
product_id: str
quantity: int
@dataclass(init=False)
class CreateOrderResponse(Model):
order_id: str
status: str
class CreateOrder(Service):
input = CreateOrderRequest
output = CreateOrderResponse
def handle(self):
request = self.request.input # type: CreateOrderRequest
# Create the order using input data
order_id = self.invoke('orders.create',
customer_id=request.customer_id,
product_id=request.product_id,
quantity=request.quantity
)
# Build response
response = CreateOrderResponse()
response.order_id = order_id
response.status = 'created'
self.response.payload = response
curl -X POST http://localhost:11223/api/orders \
-d '{"customer_id": "CUST-001", "product_id": "PROD-123", "quantity": 2}'
Benefits of data models:
after_created method for custom validation logicFor optional fields, use optional from zato.common.typing_:
from zato.common.typing_ import optional
@dataclass(init=False)
class CreateOrderRequest(Model):
customer_id: str
product_id: str
quantity: int
notes: optional[str] = None # not required
Use curly braces to capture parts of the URL as parameters. For a URL path like /api/customers/{customer_id}/orders/{order_id}, Zato extracts both values and makes them available in your service:
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class GetCustomerOrder(Service):
def handle(self):
customer_id = self.request.http.params['customer_id']
order_id = self.request.http.params['order_id']
order = self.invoke('orders.get', customer_id=customer_id, order_id=order_id)
self.response.payload = order
Query string parameters are also available through self.request.http.params:
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class SearchOrders(Service):
def handle(self):
status = self.request.http.params.get('status', 'all')
limit = int(self.request.http.params.get('limit', 100))
orders = self.invoke('orders.search', status=status, limit=limit)
self.response.payload = orders
For POST and PUT requests with JSON bodies, Zato parses the JSON automatically. Access the data through self.request.payload:
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class CreateCustomer(Service):
def handle(self):
name = self.request.payload['name']
email = self.request.payload['email']
customer = self.invoke('customers.create', name=name, email=email)
self.response.payload = customer
curl -X POST http://localhost:11223/api/customers \
-d '{"name": "Alice Smith", "email": "alice@example.com"}'
By default, a channel accepts any HTTP method. To restrict it, select a specific method in the channel configuration.
For more control, implement verb-specific handlers in your service - this lets one service handle GET, POST, PUT, and DELETE differently on the same URL.
Set the channel's data format to match what clients send:
JSON - Zato parses incoming JSON and serializes responses automatically. This is the typical choice for REST APIs. See request and response handling for details.
Form data - for HTML form submissions or webhooks sending form-encoded data. Access fields through self.request.http.POST. For file uploads, see file handling.