> Source: Onevium official documentation
> Article: External access: publish a service and send your first request (preview)
> Original URL: https://onevium.com/docs/developers/external-access
> Language: English
> Updated: 2026-09-09
> Applies to: 1.1.23-beta.7
> Feature status: Development preview

---

# External access: publish a service and send your first request (preview)

Set up an application and assistant service in the preview, send a test request, and choose queries, SSE, or public HTTPS result callbacks.

## Purpose

External access lets a business backend call a Onevium assistant through an API, continue a conversation, or start work from a signed Webhook. This guide follows the **updated 1.1.23 development-preview interaction** with **Channels → External access** and the **Connection settings** dialog. The website currently lists stable **1.1.22**; not every stable installation includes these screens. If the entry is missing, confirm that your installed preview contains this workflow.

Publishing an assistant service makes that configured service callable. It does not publish a desktop release or prove production acceptance. Real public-network and production-business validation remain separate work.

The screenshots capture real development-preview components using isolated example data. Their workspace, connection, and draft states illustrate the steps. No real business request, public-network connection, model execution, MCP connection, or callback delivery was verified in these captures.

![Create your first business application from External access.](https://onevium.com/docs/external-access/c2409f75f/en/01-start.png "Create your first business application from External access.")

## Before you start

- Use a trusted business system, a project suitable for testing, and a configured model provider. Review the [permission boundaries](https://onevium.com/docs/permissions) before allowing project changes.
- Keep Onevium running and its computer awake. A gateway receives requests; the designated Onevium device executes them. Built-in access cannot receive new requests while the computer is asleep or off.
- Start with built-in access and a terminal on the same computer. Public networking, Docker, and result callbacks are optional.

The commands below use Bash/zsh and curl syntax. On Windows, use an existing compatible terminal or implement the same HTTP methods, headers, and JSON in your backend. An application key is distinct from a model-provider API key or a private management token.

For your first local test, create an application directly: **Built into Onevium** is already the default. Open **Connection settings → Connection** only when you want to review or change the connection. Edits and mode changes remain drafts until **Save**; **Cancel** discards unsaved changes. Switching modes keeps their drafts separate. Saving a different mode pauses access, so finish setup before enabling it again. A failed save keeps the dialog and your fields available for correction.

Leave **Result callbacks** unchanged unless you need server notifications. An empty callback allowlist blocks every destination; it is not an unrestricted default. This list controls outgoing results only. Incoming API requests still use application credentials and business-user permissions.

## First task

### 1. Create an application and store its key

Choose **Create your first application** and use a recognizable name, such as “Support ticket system.” Each application represents one business system with its own credentials and conversations.

![Create a separate application for one business system.](https://onevium.com/docs/external-access/c2409f75f/en/03-create-application.png "Create a separate application for one business system.")

The application key is shown once after creation. Save it in your business backend’s credential store before closing the dialog. Keep it out of browser JavaScript, shared screenshots, source control, and URL query strings. Additional API keys can have narrower operation scopes.

This walkthrough uses `endpoints:read` to list services, `runs:write` to submit work, and `runs:read` to retrieve results. Check those scopes when using a later, restricted key. See [application keys and permissions](https://onevium.com/docs/developers/authentication) for scope meanings and key replacement.

### 2. Add a service in Basics and Capabilities

Select the application and choose **Add service**. In **Basics**, enter a service name, select the working directory, choose your provider and model, and describe the task. The folder and model pickers follow the same interaction as chat. Choose **Next** to review **Capabilities**.

| Field             | What to enter                                                                                                                               |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| Service name      | For example, “Ticket analysis assistant,” to distinguish services within this application                                                   |
| Working Directory | A real project on the device running Onevium, not a directory on the calling server                                                         |
| Model             | A configured provider and model your account can use; Opus 5 in the screenshot is only an example                                           |
| Task instructions | The fixed task for this service, such as analyzing tickets and suggesting next steps; callers later supply business content through `input` |

Do not copy `/workspace/support-demo` from the screenshot unchanged. Select your own test directory and confirm the model connection works.

![Choose the workspace and model, then describe the service task.](https://onevium.com/docs/external-access/c2409f75f/en/04-service-basics.png "Choose the workspace and model, then describe the service task.")

New services default to **Workspace tools**, with **Read, Grep, Glob, Edit, and Write** selected. These allow project file operations under the service’s approval rules; selecting a tool does not grant full access or bypass approval. Deselect capabilities you do not need. Choose **Conversation only** for a service that does not need project files.

**Run shell commands** adds Bash and is off by default. It needs an additional sandbox capability check. Selecting a capability does not establish that the current platform and runtime can publish it.

![Five project file tools are selected by default; Bash is off and operations remain subject to approval.](https://onevium.com/docs/external-access/c2409f75f/en/05-service-capabilities.png "Five project file tools are selected by default; Bash is off and operations remain subject to approval.")

### 3. Optionally select project Skills and MCP tools

Open the advanced Skills and MCP area only when needed. **Read project configuration** explicitly reads the selected project and adds eligible project Skills to the draft. Review the selections and remove unnecessary items. Only `SKILL.md` instructions are published; supporting scripts and personal skills are not imported.

![Review Skills and MCP services after reading the project configuration (example catalog).](https://onevium.com/docs/external-access/c2409f75f/en/06-project-skills.png "Review Skills and MCP services after reading the project configuration (example catalog).")

For an eligible MCP server, choose **Read tools** to contact that server and import its available tool selections, then remove any the service should not use. This path supports publishable **HTTPS MCP connections**. A discovered stdio or SSE configuration is not automatically usable; unavailable entries explain their restrictions. Reading configuration and discovering tools are separate from passing publication checks.

### 4. Save, check capabilities, publish, and enable

Choose **Save** in the service dialog. The application page shows the service as a draft. Run **Check capabilities** and inspect the result. Correct any failed capability or runtime requirement before continuing.

![Saving creates a draft; publication requires passing capability checks (example state).](https://onevium.com/docs/external-access/c2409f75f/en/08-service-draft.png "Saving creates a draft; publication requires passing capability checks (example state).")

When checks pass, choose **Publish service**, then **Enable external access** on the main page. Saved, checked, published, and enabled are separate stages. Use the resulting **API address** shown by Onevium, not the desktop application’s management address. Built-in access listens on loopback; a client on another computer needs explicitly configured HTTPS reachability or the optional remote gateway.

### 5. Copy and execute a test request

In **Try your first request**, select a published service if there are several. Expand **Send a test request** and choose **Copy example**. The generated curl includes the current gateway address, service ID, message, and headers. Replace `YOUR_APP_KEY` with this application’s key and run the command from your business backend or a terminal that can reach that address.

![Connection status and address are examples; copy the curl command, replace YOUR\_APP\_KEY, and run it yourself. Copying does not send it.](https://onevium.com/docs/external-access/c2409f75f/en/09-request-example.png "Connection status and address are examples; copy the curl command, replace YOUR_APP_KEY, and run it yourself. Copying does not send it.")

For the standalone example below, prepare these variables first. **The displayed API address already includes `/api/v1`. Remove that suffix from `GATEWAY_URL`; the commands below append it themselves.**

| Variable      | Where to obtain it                                                                                                              |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `GATEWAY_URL` | The current API address without its final `/api/v1`; `http://127.0.0.1:48541` in the screenshot is an example, not a fixed port |
| `ENDPOINT_ID` | The published service ID from the generated request path or service directory, not the application ID                           |
| `APP_KEY`     | A valid key for the current business application, supplied by your backend credential store                                     |

You can first query the application’s published service directory. This does not start a task:

```bash
curl --fail-with-body -sS "$GATEWAY_URL/api/v1/agent-endpoints" \
  -H "Authorization: Bearer $APP_KEY" \
  -H 'X-Onevium-Subject: docs-test-user'
```

Expect 200 and an `endpoints` list. If it is empty, return to the selected application and check publication rather than submitting a draft ID. Once the target is confirmed, send:

```bash
curl -X POST "$GATEWAY_URL/api/v1/agent-endpoints/$ENDPOINT_ID/runs" \
  -H "Authorization: Bearer $APP_KEY" \
  -H 'X-Onevium-Subject: docs-test-user' \
  -H 'Idempotency-Key: docs-test-run-001' \
  -H 'Content-Type: application/json' \
  --data '{"input":{"text":"Reply only: Connected"}}'
```

The in-app example already contains the address and service ID; do not append another path to it. Copying does not execute the request. “Ready to connect” in the screenshot is an isolated example state, not evidence that your environment is connected.

**Retry the same operation with the same Idempotency-Key, subject, target, and body. Use a new key for each intentionally new task.** Repeatedly executing the unchanged example retries the original task. Your authenticated backend should derive `X-Onevium-Subject` from its own user session rather than forwarding an arbitrary browser value.

## Confirm success

A **202 response and `run_id` confirm acceptance**, not successful completion. Save the returned ID as `RUN_ID` and query it with the same application identity and subject:

```bash
curl "$GATEWAY_URL/api/v1/runs/$RUN_ID" \
  -H "Authorization: Bearer $APP_KEY" \
  -H 'X-Onevium-Subject: docs-test-user'
```

Wait for the actual state and result, and compare the task with its records in the application’s **Credentials and history** area. A task awaiting approval or reconciliation does not yet have a confirmed final outcome.

Confirm whether execution started, then inspect its final execution state and public result. A successful HTTP query is not a successful task if execution failed, was cancelled, expired, or is still waiting for a device. After receiving `run_id`, keep querying that ID rather than creating new work to check progress.

For live observation, use `GET /api/v1/runs/{run_id}/events` with SSE and the same authorization. Disconnecting that observer does not cancel execution. Use explicit stop or context-reset controls, and query the returned control operation to confirm completion. A reset does not undo earlier file changes or other external work.

## Common problems

| Observation                       | What to check                                                                                                                                                                |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| The entry is missing              | Confirm that the installed preview includes external access; this guide does not change stable 1.1.22 availability.                                                          |
| Service remains a draft           | Save the configuration, run capability checks, and publish after they pass. Enable access separately.                                                                        |
| Capability check fails            | Read the reported restriction. Reduce the selection or correct the supported runtime; do not bypass the publishing gate.                                                     |
| 401 or 403                        | Check the application key, scope, subject handling, and service authorization.                                                                                               |
| 409                               | Check the conversation generation, busy state, or reuse of a key with a different body.                                                                                      |
| Accepted but unfinished           | Check that the designated device is connected and awake, then inspect approvals and task state. Retry or query the original operation instead of creating another execution. |
| A settings save fails             | Keep the draft, correct the error, and save again. A blank field for an already saved private management token preserves that secret.                                        |
| A localhost or LAN callback fails | These callback destinations are unsupported. Use API result queries or SSE for local clients.                                                                                |

## Next steps

Common request shapes are retained below. For the full procedures, read [keys and permissions](https://onevium.com/docs/developers/authentication), [conversations and run controls](https://onevium.com/docs/developers/conversations), [Webhooks and result callbacks](https://onevium.com/docs/developers/webhooks), and the [remote gateway](https://onevium.com/docs/developers/remote-gateway).

### Continue a business conversation

For a stable conversation, create a container before sending messages. Set the variables to your actual gateway, endpoint, and application key:

```bash
curl "$GATEWAY_URL/api/v1/conversations" \
  -H "Authorization: Bearer $APP_KEY" \
  -H 'X-Onevium-Subject: docs-test-user' \
  -H 'Idempotency-Key: docs-create-001' \
  -H 'Content-Type: application/json' \
  --data '{"endpoint_id":"YOUR_ENDPOINT_ID","conversation_key":"docs-demo"}'
```

Replace `YOUR_ENDPOINT_ID` with the real endpoint ID. Save the returned conversation ID as `CONVERSATION_ID`, then send a message:

```bash
curl "$GATEWAY_URL/api/v1/conversations/$CONVERSATION_ID/messages" \
  -H "Authorization: Bearer $APP_KEY" \
  -H 'X-Onevium-Subject: docs-test-user' \
  -H 'Idempotency-Key: docs-message-001' \
  -H 'Content-Type: application/json' \
  --data '{"expected_generation":1,"input":{"text":"Reply only: Connected"}}'
```

A new conversation starts at generation 1. After resetting context, read its actual generation instead of continuing to send 1. Failed sends keep their drafts; review a draft when the generation changes. Keep the original execution identity when an admission response is uncertain.

### Choose incoming webhooks, queries, SSE, or callbacks

An incoming **Webhook** receives a signed business event and maps it to work. Configure the event filter, field mapping, and signing secret under **Events and callbacks → Add webhook**. A **result callback** sends selected task events to a business server. These are different directions and separate configurations.

For built-in callbacks, open **Connection settings → Result callbacks**:

1. An empty allowlist blocks all callbacks. Enter exact hostnames, separated by commas, and **Save**. Do not include full URLs, ports, IP addresses, or wildcards.
2. Add the actual HTTPS callback URL, signing secret, and desired events for the application.
3. Inspect delivery records separately from task results. Only a destination 2xx response confirms delivery. The receiver should deduplicate repeated deliveries by event ID.

Callbacks currently support **public HTTPS destinations only**. Localhost, loopback, and private networks remain blocked even if a hostname is allowlisted. Local business clients can query results or subscribe to SSE without enabling callbacks. A remote gateway’s callback allowlist is configured on that server.

### Optionally use a remote gateway

Use a **gateway deployment package matching your Onevium version**. This tutorial does not provide a download link for a public server image. Docker and public access remain optional. A continuously running gateway can accept work while the desktop is offline, but execution still requires the designated Onevium device to reconnect and be awake.

1. In **Connection settings → Connection**, select **Remote gateway** and enter its HTTPS address. For a self-hosted server, open **Advanced remote settings** and select **Private connection via SSH**. **Save** before exporting or pairing; neither action silently saves fields or switches modes.
2. **Export device identity** downloads a public-key identity file. Use it to initialize the matching gateway package. The private key stays with Onevium.
3. Configure the gateway’s private management socket. Forward it over an authenticated SSH connection to an explicit local address, such as `http://127.0.0.1:8430`. Keep SSH host verification enabled. Enter that address and the private control token, then **Save**; leaving an already saved token field blank keeps it.
4. Choose **Pair this device** once the gateway and tunnel are ready. Then complete service publication and enable access. **Account-authenticated hosted gateway** is a separate option for a compatible hosted service, not a replacement for a self-hosted private control channel.

A public HTTPS proxy must forward only the independent gateway listener. Never expose Onevium’s management port or the private management socket. Verify reachability, pairing, capability checks, actual model execution, and any callback destination independently in the environment you intend to use.

See [team channels](https://onevium.com/docs/team-channels), [permissions](https://onevium.com/docs/permissions), and [settings and data](https://onevium.com/docs/settings-and-data) for related product boundaries.
