# Get Started (/docs/get-started)



Get credentials and call a published Void App through the Voidnet. Every request uses the same pattern regardless of the app.

## Prerequisites [#prerequisites]

* A Voidnet Console account ([sign up](https://openvoidnet.com/console))
* An HTTP client ([curl](https://curl.se), Postman, or any language)

## Step 1: Get credentials [#step-1-get-credentials]

You need a bearer credential to authenticate requests. Two options:

### Option A: API key (simplest) [#option-a-api-key-simplest]

In the Console, open **API Keys** → **Generate Key**. You get a key like:

```
vnb-sk-a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6
```

**Save it now** — it is shown only once. Lost keys must be revoked and regenerated.

| Prefix    | Type              | Use case        |
| --------- | ----------------- | --------------- |
| `vnb-sk-` | Buyer service key | General purpose |

### Option B: OAuth access token (production) [#option-b-oauth-access-token-production]

Exchange an API key for a short-lived JWT. Better for production because tokens expire and can be scoped.

```bash
curl -X POST https://api.openvoidnet.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=vnb-sk-a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6"
```

Response:

```json
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "mcp:tools"
}
```

The `access_token` is a JWT valid for 1 hour. Use it as a `Bearer` credential anywhere you would use an API key. When it expires the gateway returns `401 api_key_expired` — request a new token and retry.

The `scope` defaults to `mcp:tools`. A token with an `mcp:` prefix can call any MCP method; `llm:completions` can call LLM `chat/completions`. Example `llm:completions` or `mcp:tools llm:completions`. Empty scope (legacy keys) is unrestricted.

## Step 2: Find an app [#step-2-find-an-app]

Browse the [Marketplace](https://openvoidnet.com/marketplace). Note two things about the app you want:

* **Publisher username** — the developer's public identifier (e.g. `acmecorp`)
* **App name** — unique per publisher (e.g. `weather-tools`)

Purchase the app to gain access. Apps offer free tiers, paid tiers, or both:

* **Free tier** — click Get Free. Access is instant.
* **Paid tier** — click Subscribe/Purchase. Paid access runs on wallet: top up at **Console → Wallet** ($5–$1000 via Stripe), and the price deducts automatically.
* **Upgrade** — own free and want paid? The app page shows an Upgrade button; free access is revoked when the paid grant completes.

**Stateless MCP 2026-07-28:**
  You do not need sessions, initialize handshake, or SSE to call a tool. Just POST with the required headers.


## Step 3: Send your first request [#step-3-send-your-first-request]

The URL encodes the protocol, publisher, and app:

```
POST /v1-beta/{adapter}/{username}/{appname}
```

For MCP tools the adapter is `mcp`. For AI models the adapter is `llm`. Example using the test app:

```bash
curl -X POST https://api.openvoidnet.com/v1-beta/mcp/acmecorp/weather-tools \
  -H "Authorization: Bearer vnb-sk-a1b2c3d4e5f6..." \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/list" \
  -H "Mcp-Name: tools/list" \
  -d '{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "tools/list"
  }'
```

**Required headers:**

* `Authorization: Bearer <credential>`
* `MCP-Protocol-Version: 2026-07-28`
* `Mcp-Method: <method>` (e.g., `tools/list`)
* `Mcp-Name: <name>` (e.g., `tools/list`)

**Stateless MCP 2026-07-28** — No sessions, no initialize handshake, no `Mcp-Session-Id`, no GET/DELETE endpoints.

Response (the exact tools depend on the publisher):

```json
{
  "jsonrpc": "2.0",
  "id": "1",
  "result": {
    "tools": [
      {
        "name": "get_forecast",
        "description": "Get weather forecast for a location",
        "inputSchema": {
          "type": "object",
          "properties": {
            "location": { "type": "string", "description": "City name or coordinates" },
            "days": { "type": "integer", "description": "Number of days (1-7)" }
          },
          "required": ["location"]
        }
      }
    ],
    "ttlMs": 300000,
    "cacheScope": "private"
  }
}
```

## Step 4: Call a tool [#step-4-call-a-tool]

Use `tools/call` with the tool name and arguments:

```bash
curl -X POST https://api.openvoidnet.com/v1-beta/mcp/acmecorp/weather-tools \
  -H "Authorization: Bearer vnb-sk-a1b2c3d4e5f6..." \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/call" \
  -H "Mcp-Name: get_forecast" \
  -d '{
    "jsonrpc": "2.0",
    "id": "2",
    "method": "tools/call",
    "params": {
      "name": "get_forecast",
      "arguments": { "location": "London", "days": 3 }
    }
  }'
```

### Try LLM [#try-llm]

```bash
curl -X POST https://api.openvoidnet.com/v1-beta/llm/acmecorp/my-llm \
  -H "Authorization: Bearer vnb-sk-a1b2c3..." \
  -H "Content-Type: application/json" \
  -d '{"model":"Qwen/Qwen2.5-7B-Instruct","messages":[{"role":"user","content":"Hello!"}],"stream":false}'

# Or OpenAI SDK:
# from openai import OpenAI; client = OpenAI(base_url="https://api.openvoidnet.com/v1-beta/llm/acmecorp/my-llm", api_key="vnb-sk-...")
# client.chat.completions.create(model="Qwen/Qwen2.5-7B-Instruct", messages=[{"role":"user","content":"hi"}])
```

## Next steps [#next-steps]

* [Buyer Guide (MCP)](https://docs.openvoidnet.com/docs/mcp/buyer) — OAuth (client\_credentials, authorization\_code+PKCE, refresh\_token), rate limits, advanced patterns
* [Buyer Guide (LLM)](https://docs.openvoidnet.com/docs/llm/buyer) — OpenAI-compatible calls via SDK
* [Publisher Guide (LLM)](https://docs.openvoidnet.com/docs/llm/publisher) — host with vLLM/Ollama and publish
* [API Reference](https://docs.openvoidnet.com/docs/reference/api-reference) — complete, generated from the gateway source
* [Error Reference](https://docs.openvoidnet.com/docs/reference/error-reference) — full error code catalog
