# Operation

URL: /define/operations · Id: `term:operation`

> One callable Verb on a Noun, named by its operationId, with its path, parameters, return schema, example, price and run.

An Operation is one callable Verb on a Noun, named by its operationId, with its path, parameters, return schema, example, price and run.

## Parts
| Field | Type | Required | What it is |
| --- | --- | --- | --- |
| `verb` | `string` | Yes | The operationId: lowerCamelCase, unique, and the same name on every Interface. |
| `method` | `"GET"` | Yes | The HTTP method; every proven operation is a lookup. |
| `path` | `string` | Yes | An OpenAPI path template, such as `/places/{placeId}/hours`. |
| `summary` | `string` | Yes | One line that names what the operation answers. |
| `description` | `string` | Yes | The docs text for the operation. |
| `params` | `Param[]` | Yes | Each parameter: its name, place, type, description, and whether it is required. |
| `returns` | `JSON Schema` | Yes | The schema of the answer, printed in OpenAPI and the SDK types. |
| `example` | `{ input, output }` | Yes | One input and its exact output; the contract tests run it through every Interface. |
| `price` | `number` | Yes | The posted rate per call that returns a result, 0 or more; it is stored on the Offer. |
| `run` | `Run` | Yes | How the operation answers, as data and never as code. |

## Kinds
| Run | Answers |
| --- | --- |
| `get` | One record of the Startup's own collection, keyed by a parameter. |
| `list` | The records of a collection of the Startup, filtered by equality on the parameters given. |

## Checks
- An API declares at least one operation.
- A verb is lowerCamelCase.
- No two operations share a verb.
- No operation is named `batch`: the Batch route takes it.
- A path starts with a slash and holds only path characters and parameters.
- No two operations serve the same route.
- No operation takes a reserved path.
- Every parameter in a path is declared as a path parameter.
- Every path parameter appears in the path.
- Every path parameter is required.
- A price is a number, 0 or more.

The reserved paths are `/`, `/mcp`, `/docs`, `/openapi.json`, `/llms.txt`, `/pricing`, `/.well-known`, `/sdk`, `/batch`, `/dashboard` ([what each serves](/interfaces#reserved-paths)).

## Example
```json title="getHours, the Hours.get operation of openhours.example"
{
  "verb": "getHours",
  "method": "GET",
  "path": "/places/{placeId}/hours",
  "summary": "The opening hours of one place",
  "description": "Answers the weekly opening hours of one place, in the place's own timezone.",
  "params": [
    {
      "name": "placeId",
      "in": "path",
      "type": "string",
      "required": true,
      "description": "The place id",
      "example": "pl_4821"
    }
  ],
  "returns": {
    "type": "object",
    "properties": {
      "placeId": { "type": "string" },
      "timezone": { "type": "string" },
      "open": { "type": "array" }
    }
  },
  "example": {
    "input": { "placeId": "pl_4821" },
    "output": {
      "placeId": "pl_4821",
      "timezone": "Europe/Lisbon",
      "open": [{ "day": "mon", "from": "09:00", "to": "18:00" }]
    }
  },
  "price": 0.002,
  "run": { "kind": "get", "collection": "hours", "key": "placeId" }
}
```