> For the complete documentation index, see [llms.txt](https://docs.nerovasystems.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nerovasystems.com/guides/zero-to-live/step-11-go-live.md).

# Step 10: Go live

Prove the integration end to end on your Live key, read and drive the conversation, and pass the production gate.

{% hint style="info" %}
Requires [Step 9: Webhooks today](/guides/zero-to-live/step-9-webhooks.md).
{% endhint %}

**Step 10 of 10.** Everything is wired: tenant, connection, capabilities, activation, channel. In this step you prove the integration end to end on the Live key you already use, read and drive a conversation through the API, and pass the production gate. You keep the same key, host, and tenants throughout; there is no environment to switch to.

## 10.1 Prove a booking end to end

Use the tenant you activated in step 7 with your test WhatsApp number bound in step 8, and a phone you control as the customer.

1. Message the business number and ask for a booking, for example "Can I book a cut on Friday morning?".
2. The digital employee reads your Provider API for services and availability, offers slots, and creates the appointment when you confirm.
3. Check your own system of record. The appointment exists, with the references your Provider API serves.
4. Read the work ledger to see the verified outcome:

```bash
curl "https://api.nerovasystems.com/api/v1/tenants/{tenantId}/work?Limit=10" \
  -H "Authorization: Bearer $NEROVA_API_KEY"
```

An entry is only verified when the platform read the appointment back from your provider after creating it and confirmed the write landed in your system of record. That read after write verification is the discipline the digital employee applies to every real booking. Log the `X-Request-Id` of each call next to your own test assertions so you can trace them back to exact requests.

Every message and booking during this proof draws on your free testing allowance of 5,000,000 tokens, which is never invoiced. If the allowance runs out before a commercial agreement is signed or a card is saved, the key and the AI pause. See [From approval to your first invoice](https://docs.nerovasystems.com/documentation/console/platform-access#from-approval-to-your-first-invoice).

<figure><img src="https://688612263-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFbXqEX8kMjYyctZN2zcq%2Fuploads%2Fgit-blob-c9c1a0513f6081cfc2dc417960b38db50ba11ec4%2Fconsole-workbench.png?alt=media" alt="Workbench running requests"><figcaption><p>The console's Workbench runs the same requests interactively and shows each operation's result.</p></figcaption></figure>

## 10.2 Read and drive the conversation

The conversation surface lives under `/api/v1` alongside everything else you have used since step 2. Reads require the `conversation:read` scope; sending requires `conversation:write`.

List the tenant's conversations:

{% tabs %}
{% tab title="curl" %}

```bash
curl https://api.nerovasystems.com/api/v1/tenants/{tenantId}/conversations \
  -H "Authorization: Bearer $NEROVA_API_KEY"
```

{% endtab %}

{% tab title="C#" %}

```csharp
// client construction: see the .NET SDK page (docs.nerovasystems.com/sdks/dotnet)
var tenantId = "1539251826400956416"; // from step 4
var page = await client.Api.V1.Tenants[tenantId].Conversations.GetAsync();
foreach (var conversation in page?.Items ?? [])
{
    Console.WriteLine($"{conversation.Id} ({conversation.Channel}): {conversation.Status}");
}
```

{% endtab %}

{% tab title="TypeScript" %}

```typescript
// client construction: see the TypeScript SDK page (docs.nerovasystems.com/sdks/typescript)
const tenantId = "1539251826400956416"; // from step 4
const page = await client.api.v1.tenants.byTenantId(tenantId).conversations.get();
for (const conversation of page?.items ?? []) {
  console.log(`${conversation.id} (${conversation.channel}): ${conversation.status}`);
}
```

{% endtab %}
{% endtabs %}

The page carries `availability`, `items`, `nextCursor`, and `transcriptRetentionDays`. Expect an empty `items` array until the first customer message has arrived.

Read one conversation, transcript included:

{% tabs %}
{% tab title="curl" %}

```bash
curl https://api.nerovasystems.com/api/v1/tenants/{tenantId}/conversations/{conversationId} \
  -H "Authorization: Bearer $NEROVA_API_KEY"
```

{% endtab %}

{% tab title="C#" %}

```csharp
var conversationId = "01M0AEB7QJ5N3P7T2X8C4V0B6D"; // an id from the list call
var conversation = await client.Api.V1.Tenants[tenantId]
    .Conversations[conversationId].GetAsync();

foreach (var message in conversation?.Messages ?? [])
{
    Console.WriteLine($"[{message.Direction}] {message.Content}");
}
```

{% endtab %}

{% tab title="TypeScript" %}

```typescript
const conversationId = "01M0AEB7QJ5N3P7T2X8C4V0B6D"; // an id from the list call
const conversation = await client.api.v1.tenants.byTenantId(tenantId)
  .conversations.byConversationId(conversationId).get();

for (const message of conversation?.messages ?? []) {
  console.log(`[${message.direction}] ${message.content}`);
}
```

{% endtab %}
{% endtabs %}

Each transcript message carries `id`, `direction`, `content`, `status`, `sentAt`, and a `redaction` marker.

Send a message into a conversation:

{% tabs %}
{% tab title="curl" %}

```bash
curl -X POST https://api.nerovasystems.com/api/v1/tenants/{tenantId}/conversations/{conversationId}/messages \
  -H "Authorization: Bearer $NEROVA_API_KEY" \
  -H "Idempotency-Key: 6c1f2a3b-4d5e-4f6a-8b7c-9d0e1f2a3b4c" \
  -H "Content-Type: application/json" \
  -d '{ "text": "Thanks, see you on the 15th." }'
```

{% endtab %}

{% tab title="C#" %}

```csharp
using Nerova.Sdk.Models;

var sent = await client.Api.V1.Tenants[tenantId]
    .Conversations[conversationId].Messages.PostAsync(
        new SendPartnerRuntimeMessageCommand { Text = "Thanks, see you on the 15th." },
        requestConfiguration => requestConfiguration.Headers.Add(
            "Idempotency-Key", "6c1f2a3b-4d5e-4f6a-8b7c-9d0e1f2a3b4c")
    );
```

{% endtab %}

{% tab title="TypeScript" %}

```typescript
const sent = await client.api.v1.tenants.byTenantId(tenantId)
  .conversations.byConversationId(conversationId).messages.post(
    { text: "Thanks, see you on the 15th." },
    { headers: { "Idempotency-Key": "6c1f2a3b-4d5e-4f6a-8b7c-9d0e1f2a3b4c" } },
  );
```

{% endtab %}
{% endtabs %}

HTTP 200 returns the action record:

```json
{
  "actionId": "01M0AEB7Q4XZ2M8K5W1R9T3V6Y",
  "resourceType": "conversation",
  "resourceId": "01M0AEB7QJ5N3P7T2X8C4V0B6D",
  "state": "sent",
  "version": "v1:8c4f2a1e9b3d5c7f0a2e4b6d",
  "idempotencyStatus": "applied"
}
```

Two conflict cases matter. The send is rejected with HTTP 409 when the channel is not ready or the customer service window for the conversation has closed. And if delivery could not be verified, the 409 carries the code `partner.action_outcome_unknown`: read the conversation back to see whether the message landed before retrying with a new idempotency key.

## 10.3 The production gate

Production use is gated on four things, all checked automatically:

1. **Certification.** Your provider connection must be `Certified` (step 6.3): a recorded conformance run against your real endpoint.
2. **Billing.** An active billing relationship for your platform organization: a commercial agreement that Nerova staff mark signed (billed by monthly invoice, payable within 30 days) or a card saved under **Billing details** (charged automatically at period close).
3. **Release proof.** The evidence trail from this journey (activation receipts, conformance results, the verified booking from 10.1) attached to your organization.
4. **Entitlement.** The platform's own decision that your organization may operate in Production, visible on `GET /api/v1/context` as `productionDecision`.

You can check where you stand at any time with the same context call from step 2.3: `entitlementState` and `productionDecision` tell you whether the gate is open. A denied call in Production fails with a problem details response naming the missing prerequisite rather than a generic error.

## 10.4 Go live with real merchants

Going live does not change your key or your host. The difference is the tenants you point it at:

1. Provision each real merchant (step 4) with its production `externalReference`.
2. Connect it to your production Provider API endpoint with a production credential (step 5).
3. Confirm capabilities verify against the real endpoint (step 6).
4. Run activation with the merchant's real mandate choices and real consent actors (step 7), binding the merchant's real WhatsApp presence through the hosted link (step 8).
5. Hold the activation receipt. It is the durable record that this merchant, on this date, authorized this mandate.

Activation switches the tenant's AI receptionist on. Because every step is idempotent and versioned, the automation you built while testing runs unchanged: only the merchant and its reference values differ. Keep test tenants clearly labelled in your own system, and deactivate them when you are done.

## 10.5 Operating in production

* Poll the surfaces from step 9.2 for provisioning, health, and runtime activity.
* Watch connection `health`: the platform fails closed on `Unavailable` and routes affected work to humans.
* Track usage per tenant through the usage surface and your platform's billing state through the console. Once the free testing allowance is spent, usage is billed.
* Rotate keys from the console; mint the replacement first, deploy it, then revoke the old one.

## You are live

A merchant's digital employee is Active on a real channel, acting within a recorded mandate, against your certified integration. From here the reference documentation on [docs.nerovasystems.com](https://docs.nerovasystems.com) is your day to day companion. Welcome aboard.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.nerovasystems.com/guides/zero-to-live/step-11-go-live.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
