# REST in Python

Accept REST calls, react to HTTP verbs and invoke REST APIs from Python services.

REST channels expose your services as HTTPS endpoints and outgoing REST connections let your services call other APIs. Both are defined once, in the Dashboard or in enmasse, and your code refers to them by name.

## Accept a REST call {#accept-a-rest-call}

The parsed JSON request is `self.request.payload` and whatever you assign to `self.response.payload` is serialized to JSON for the caller:

```python
from zato.server.service import Service

class GetCustomer(Service):

    input = 'customer_id'
    output = 'customer_id', 'name', 'status'

    def handle(self):

        customer_id = self.request.input.customer_id

        self.response.payload.customer_id = customer_id
        self.response.payload.name = 'Jane Doe'
        self.response.payload.status = 'active'
```

Invoke it:

```bash
curl localhost:11223/api/customers -d '{"customer_id":"123"}'
```

## React to HTTP verbs {#react-to-http-verbs}

Implement `handle_<VERB>` methods and each verb gets its own code path - a verb with no method receives `405 Method Not Allowed`:

```python
from zato.server.service import Service

class Customers(Service):

    def handle_GET(self):
        self.response.payload = {'customers': ['123', '456']}

    def handle_POST(self):
        customer = self.request.payload
        self.logger.info('Creating customer: %s', customer['name'])
        self.response.status_code = 201
```

## Call a REST API {#call-a-rest-api}

Look up an outgoing connection by name and call it with the verb you need - the payload, query parameters and headers are plain dicts and the response's JSON is already parsed in `response.data`:

```python
from zato.server.service import Service

class SetBillingInfo(Service):

    def handle(self):

        payload = {'billing': '395.7', 'currency': 'EUR'}
        params = {'cust_id': '39175', 'priority': 'normal'}
        headers = {'X-App-Name': 'Zato'}

        conn = self.rest['Billing API']
        response = conn.post(payload, params, headers=headers)

        self.response.payload = response.data
```

The same connection object has `.get`, `.put`, `.patch` and `.delete` too, and `response.status_code` is the HTTP status the API returned.

## Path parameters {#path-parameters}

If the connection's URL path contains a pattern, e.g. `/api/billing/{phone_no}`, the matching key from `params` fills it in and the remaining keys go to the query string:

```python
from zato.server.service import Service

class GetBillingInfo(Service):

    def handle(self):

        params = {'phone_no': '271637517', 'period': '2026-08'}

        conn = self.rest['Billing API']
        response = conn.get(params=params)

        self.response.payload = response.data
```

## Configuration {#configuration}

The [enmasse](https://zato.io/docs/admin/enmasse-reference.html#rest-channels) YAML for the channel and the outgoing connection the examples above use:

```yaml
channel_rest:
  - name: api.customers
    service: get-customer
    url_path: /api/customers
    security: api.customers.key

outgoing_rest:
  - name: Billing API
    host: https://billing.example.com
    url_path: /api/billing/{phone_no}
    data_format: json
    security: billing.bearer_token
```

## See also {#see-also}

- [REST channels](https://zato.io/docs/dev/rest/channels.html) - Every option of a channel, from URL matching to CORS
- [Calling REST APIs](https://zato.io/docs/dev/rest/calling-apis.html) - Retries, timeouts, errors and responses of outgoing calls
- [Authentication](https://zato.io/docs/dev/rest/authentication.html) - API keys, Basic Auth, OAuth and bearer tokens on both sides
- [Data models](https://zato.io/docs/dev/examples/model.html) - Typed request and response contracts for REST services

## Learn more {#learn-more}

- [Development documentation](https://zato.io/docs/dev/) - The complete reference for writing services
- [Requests and responses](https://zato.io/docs/dev/request-response/) - What a service receives, what it returns and how both are structured
- [Integration examples](https://zato.io/docs/dev/examples/) - Ready-made code for the systems you are likely to connect to
- [IDE and debugging](https://zato.io/docs/dev/ide/) - Write services in the Dashboard or in your own editor
- [Data models](https://zato.io/docs/dev/model/) - Declare inputs and outputs and have them validated for you
- [In-depth API tutorial](https://zato.io/tutorials/main/01.html) - The full platform tutorial, from installation to production patterns
