# Service API

Source: https://docs.oiy.ai/docs/api/services

Create a container service and control its lifecycle.



## Create a service [#create-a-service]

`POST /api/services` requires authentication and an idempotency key.

```json
{
  "name": "my-workspace",
  "region": "standard",
  "geography": "auto",
  "image": "oiy-ai-pytorch-images.xsun.workers.dev/oiy-ai-pytorch@sha256:75e3759275db19bdf2cf34b7dd59e2fc8bbf381faf91a194f05224a0f8d62302",
  "command": ["python", "-m", "http.server", "8080", "--bind", "0.0.0.0", "--directory", "/workspace"],
  "resources": { "gpuCount": 0, "cpu": 2, "memoryGb": 4 },
  "httpPort": 8080,
  "volumeGb": 20,
  "volumeMode": "independent",
  "sleepAfterMinutes": 15
}
```

This uses the digest-pinned runtime image from Oiy's built-in templates. Compare it with the current catalog before deploying. This CPU-only example starts Python's simple HTTP server for learning; it is not a production inference server. Creating it allocates paid resources when accepted. Save it as `service.json` and review the placement and estimate first. For the full create, access, pause, and resume sequence, follow [Deploy an HTTP container](/docs/http-quickstart).

```sh
curl "$OIY_API_URL/api/services" \
  -H "Authorization: Bearer $OIY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: YOUR_UNIQUE_REQUEST_ID" \
  --data-binary @service.json
```

`image`, `name`, `region`, and `resources` are required. [Configuration defaults](/docs/services/configuration) cover optional fields. Use `volumeId` to attach an existing independent volume rather than creating new storage.

## Inspect [#inspect]

`GET /api/services/{id}` returns `{ "service": ... }`. The service includes state, revision, resources, resolved geography, endpoint, and environment variable names. Use `GET /api/account` for the account's service collection; there is no standalone `GET /api/services` list route in this version.

## Lifecycle action [#lifecycle-action]

`POST /api/services/{id}/actions` accepts:

```json
{ "action": "stop" }
```

Actions are `start`, `stop`, `restart`, `resize`, and `delete`. **Only resize** accepts—and requires—the full `resources` object. Other actions reject it. Creation, start, restart, and resize require verified identity and admission checks. Delete removes service-owned storage; independent storage remains.

## Configuration patch [#configuration-patch]

`PATCH /api/services/{id}` accepts:

```json
{
  "revision": 1,
  "patch": { "httpPort": 8080 }
}
```

Use the actual current revision. Patchable fields are image, command, environment, and HTTP port. An included environment map replaces all previous entries; omitting it preserves existing values.

## Other service routes [#other-service-routes]

| Method | Path                                 | Use                                                                         |
| ------ | ------------------------------------ | --------------------------------------------------------------------------- |
| PATCH  | `/api/services/{id}/sleep`           | `{ "sleepAfterMinutes": 15 }` or `null` to disable                          |
| GET    | `/api/services/{id}/events`          | Lifecycle events                                                            |
| GET    | `/api/services/{id}/metrics`         | Monitoring for `minutes=15`, `60`, or `360`; requires configured collection |
| GET    | `/api/services/{id}/logs`            | Plain-text container logs                                                   |
| POST   | `/api/services/{id}/exec`            | Bounded command execution                                                   |
| GET    | `/api/services/{id}/activity`        | Active task/connection records                                              |
| POST   | `/api/services/{id}/activity`        | Register, heartbeat, or release a task                                      |
| POST   | `/api/services/{id}/browser-session` | Browser launch URL when supported                                           |

An activity body contains a UUID `id`, a `name` up to 128 characters, and `release` (defaults to false). Keep the same activity ID for heartbeats and final release. Use the SDK context manager for normal task protection.

## Response shapes [#response-shapes]

Create, configuration update, lifecycle action, and sleep-policy update return a **bare Service object**. `GET /api/services/{id}` wraps the same public shape as `{ "service": ... }`. There is no generic `{ "operation": ... }` acknowledgement wrapper for these actions.

An activity update returns `id`, `heartbeatSeconds: 30`, and `expiresInSeconds: 300`. That expiry is a freshness signal: stale task records remain protective rather than proving the task finished. The activity list is `{ "activities": [...] }`.

Events are `{ "events": [...] }`, newest first, with up to 100 records containing `message` and `created_at` (Unix milliseconds). Browser-session creation returns `{ "url": ... }`; keep that launch URL private.

See [resource monitoring](/docs/services/monitoring) for sampling and freshness, and the [OpenAPI description](/docs/api/openapi) for complete response field definitions.

[Restart semantics](/docs/services/restart) explain the allocated-state requirement, persistent workspace, and replacement retry behavior.
