Embedding the sales agent in your own chat or ticket softwareAll articles

Embedding the sales agent in your own chat or ticket software

Not everyone wants a third-party widget. This case shows how a software vendor brings the agent into its own system without handing it control of the cart.

Published: 2026-09-12Reading time: 5 mintapinomahub API & workflows
API & processesAPIMarketplaces

A software vendor runs its own ticket and chat system for parts dealers. Customers should get answers faster, but nobody wants a language model changing addresses or sending return labels on its own. The question is therefore not whether answers are automatic, but who is allowed to act.

The agent drafts, your system actsInput: your own chat or ticket system that needs answers but wants to act itself 1. Read the contract (GET /agent/capabilities): actionTypes, intents and limits — read once at integration instead of hard-coded 2. Create the conversation (POST /agent/conversations): profileId required, optionally channel and threadKey; back come conversationId and greeting 3. Run a turn (POST /agent/conversations/{conversationId}/messages): reply and actions; requiresConfirmation waits for your confirmation in the next turn 4. Append without a turn (POST /agent/conversations/{conversationId}/ingest): author end_user or note — stored without asking the model 5. Close the conversation (POST /agent/conversations/{conversationId}/close): outcome such as sold, not_sold or handed_over, plus orderRef Output: answers from the agent, actions from your system — actions with requiresConfirmation are confirmed by your system in the next turn via confirmations The agent does not execute actions itself. It proposes them; result and confirmation return with the next turn as toolResults and confirmations.The agent drafts, your system actsInput: your own chat or ticket system that needs answers but wants to act itself01Read the contractGET /agent/capabilitiesactionTypes, intents and limits — read once at integration instead of hard-coded02Create the conversationPOST /agent/conversationsprofileId required, optionally channel and threadKey; back come conversationId and greeting03Run a turnPOST /agent/conversations/{conversationId}/messagesreply and actions; requiresConfirmation waits for your confirmation in the next turn04Append without a turnPOST /agent/conversations/{conversationId}/ingestauthor end_user or note — stored without asking the model05Close the conversationPOST /agent/conversations/{conversationId}/closeoutcome such as sold, not_sold or handed_over, plus orderRefOutput: answers from the agent, actions from your system — actions with requiresConfirmation areconfirmed by your system in the next turn via confirmationsThe agent does not execute actions itself. It proposes them; result and confirmation return with the next turnas toolResults and confirmations.
Five calls from contract to close. Actions arrive as proposals and return as results.

The agent’s Hub interface separates the two cleanly: a turn returns the reply and a list of actions your system should carry out. Anything carrying requiresConfirmation happens only when your system confirms it in the next turn. The agent drafts, your system acts.

SurfaceRoles
Sales agentSoftware vendor, Platform and marketplace, Parts trading

What this case requires

  • A configured profile. POST /agent/conversations requires a profileId; without a profile there is no instruction, no tone and no permissions.
  • Your own tools for the actions. Whatever the agent proposes, your system must be able to carry out — a shipment status, an address change, a return label.
  • Somewhere to obtain confirmations. An action with requiresConfirmation waits for an explicit yes.
  • The API key on the server. This interface is meant for your backend, not for the customer’s browser.

The sequence

The table names the responsible call per stage and what exists afterwards. The reasoning for why a stage cannot be skipped follows below it.

The call chain of this use case
StageCallWhat exists afterwards
Read the contractGET /agent/capabilitiesactionTypes, intents and limits — read once at integration instead of hard-coded
Create the conversationPOST /agent/conversationsprofileId required, optionally channel and threadKey; back come conversationId and greeting
Run a turnPOST /agent/conversations/{conversationId}/messagesreply and actions; requiresConfirmation waits for your confirmation in the next turn
Append without a turnPOST /agent/conversations/{conversationId}/ingestauthor end_user or note — stored without asking the model
Close the conversationPOST /agent/conversations/{conversationId}/closeoutcome such as sold, not_sold or handed_over, plus orderRef

Why each stage is needed

  1. Read the contract. GET /agent/capabilities names formats, channels, actionTypes, intents and limits. The contract explicitly recommends reading it once at integration instead of hard-coding limits — otherwise your integration quietly goes out of date with the next extension.
  2. Create the conversation. POST /agent/conversations requires profileId and optionally takes, among others, channel, threadKey, subject and externalRef. The contract does not describe what threadKey does on creation; GET /agent/inbox/conversations can be filtered by threadKey as an exact thread key.
  3. Run the turn. POST /agent/conversations/{conversationId}/messages returns reply, intent, needsHuman, findings and actions. Each action carries a typecustomer_tool, hub_call, handoff or request_photo — and where needed requiresConfirmation. Results go back in the next turn as toolResults, confirmations as confirmations.
  4. Append without a turn. POST /agent/conversations/{conversationId}/ingest stores a message or an internal note with author end_user or note, without asking the model. That is the route for conversations a colleague is currently handling.
  5. Close the conversation. POST /agent/conversations/{conversationId}/close takes an outcome — such as sold, not_sold, handed_over or spam — and optionally orderRef. Closing is no formality: only with it can you evaluate what the agent actually achieved.
Confirm a proposed action in the next turn
curl -X POST \
  -H 'X-Api-Key: <API_KEY>' \
  -H 'Content-Type: application/json' \
  -d '{"confirmations":[{"actionId":"<actionId>","confirmed":true}]}' \
  'https://api.tapinomahub.com/hub/index.php/agent/conversations/<conversationId>/messages'

What you end up with

In the end your system answers faster without the agent ever changing anything about an order itself. Every action passes through your tools, every sensitive action through a confirmation — and every conversation ends with an evaluable outcome.

Where to find this in the documentation

The binding field lists, error codes and sample responses live in this surface’s OpenAPI contract at docs.tapinomahub.com (tapinoma-agent). All use cases arranged by surface and role: overview of the use cases.

Frequently asked

Does the agent execute actions itself?

No. It delivers them as proposals in actions. Your system carries them out and reports the result in the next turn as toolResults.

Why is there ingest when there are turns?

For messages the model should not answer — for example when a colleague is handling the conversation or an internal note belongs to it. Such messages do not ask the model.

Do I have to maintain limits such as message length myself?

No. They live in GET /agent/capabilities under limits. Read them at integration instead of hard-coding them.