Skip to content
Coritan Docs

Answer customer conversations

Work the support queue, answer customers, pass conversations between tiers and ask for a customer's logs or server access in the staff console.

View as Markdown

/staff/inbox in the staff console holds every support conversation between your organization and its customers. A conversation is one thread with one customer, with a number of its own in your organization such as #1042; the console calls it a ticket. Use the inbox to take conversations from the queue, answer them, pass them to a teammate or a higher tier, and ask the customer for their server's logs or for access to the server.

Readonly members cannot open the inbox. Each role can do everything the roles below it can, and billing, admin and owner can do everything Tier 3 can.

Task Lowest role
Take conversations from the queue, reply, add internal notes, close and reopen Tier 1 support
Ask a customer for their server's logs Tier 1 support
Read every conversation, and take ones escalated to Tier 2 Tier 2 support
Ask a customer for access to their server Tier 2 support
Act on any conversation, give one to a teammate, or move one to another customer Tier 3 support
Open a conversation for a customer, escalate one to Coritan, or change many at once Tier 3 support
Write, change and delete saved replies Tier 3 support

How far each tier reaches:

  • Tier 1 sees the queue and the conversations it holds. Any other conversation answers 404 Conversation not found.
  • Tier 2 reads every conversation. It acts on its own conversations and on unclaimed ones that are not escalated above Tier 2, and it can leave an internal note on a teammate's conversation.
  • Tier 3 acts on every conversation.

A Tier 1 member may hold 10 open conversations at once. An admin can set another number from 1 to 100, as Manage the staff team and console settings explains. The other roles have no limit.

Know where conversations come from

Section titled Know where conversations come from

Conversations reach the inbox from:

  • customers, from your storefront's support page or through the API with their customer token;
  • email to your brand's support mailbox, when we run one for you;
  • the /support command in your Discord server, when you connect Discord;
  • a free customer's request for an extra port, tagged port-request, as Add a port for a port request explains;
  • a customer's request for a higher mail relay limit, tagged mail and limit-increase, as Pass on a request for a higher limit explains;
  • your storefront's contact form, when a signed-in customer sends it, in the sales department and tagged storefront-inquiry;
  • your team's actions on many servers, and our abuse review's locks, in the abuse department;
  • your team, when it opens a conversation for a customer.

Coritan can run a support mailbox for your brand, such as support@ your domain; contact support to have one. Email to it opens a conversation for the customer whose address sent it, and their replies to our emails go back into the same conversation. We open one only when the address belongs to one of your customers, our mail server verified that the message came from it, and the customer may open a conversation. Otherwise we reply at most once a day to say how to reach you, and we never reply to unverified mail from someone with no account. Mail to abuse@ and postmaster@ always opens a conversation. We cut a body at 10,000 characters, and leave out attachments over 25 MB and any after the 20th, with a line in the message that names what we left out.

  1. Open /staff/inbox. The queue lists the conversations nobody holds that wait for your team at your tier or below: paying customers first, then the highest priority, then the oldest.
  2. Take the next conversation. We give you the one at the front of the queue, and two members who take at the same moment get different conversations. It becomes yours and in_progress.
  3. To answer a particular one instead, open it from the list and take it.

Besides the queue, the inbox lists your own conversations and every conversation your tier may read. Search by subject, the last message, the customer's email or a number such as #1042, and narrow the list by status, priority, department, escalation, or paying or free customers. Tier 3 can list the conversations one teammate holds, and sees how many each member holds and when they last replied.

The figures above the list count the conversations waiting, open, on hold and past their targets, how long the oldest has waited, how many your team closed today in your brand's time zone, and how many you hold against your limit.

A conversation moves through these statuses:

Status What it means
open New or reopened.
awaiting_agent The customer wrote last.
in_progress A member took it and has not replied yet.
awaiting_customer Your team wrote last.
on_hold A member set it aside, out of the queue.
closed Settled. The customer can reopen it.

Every conversation can carry a department. The departments are the same for every organization on Coritan, and each sets a target time for the first reply and one for the resolution. A conversation past either target counts as breached.

  1. Open the conversation. Beside it the console shows the customer's account: its standing, wallet, services, other open conversations, last invoices and notes.
  2. Write your reply, or insert a saved reply. A saved reply can hold placeholders such as {{first_name}}, {{ticket}} and {{server}}, which the console fills in for this conversation.
  3. Send it. To settle the matter with this reply, send and close in one step.

We email your reply to the customer, and they also read it on your storefront's support page. Replying to a conversation nobody holds makes it yours, within your claim limit, unless you close it with the same reply. Replying to a closed conversation reopens it.

  • Add an internal note to tell your team something. The customer never sees it.
  • Save a note on the customer instead when the next person to help them should see it on every conversation of theirs.
  • The console shows which teammates have the conversation open, so two people do not answer at once.
  • Change the priority, department or status as the work moves. Tier 3 can also move the conversation to another of your customers.

Close a conversation when the matter is settled. The customer can reopen it, and once it is closed they can rate it from 1 to 5 with a comment. Closing ends any server access the conversation lent, as Ask for logs or server access explains.

When a customer writes about the same matter twice, close one conversation as a duplicate of the other. Both must belong to that customer, and the one you keep must be open. We tell the customer that the matter carries on in the other conversation, and leave an internal note there that points back.

  • Release it to put it back in the queue for whoever takes it next, with a note on what you found. We keep the note as an internal note. You can release your own conversations, and Tier 3 can release anyone's.
  • Transfer it to a teammate, or to a department. A transfer to a department puts it back in the queue there and sets its targets to that department's.
  • Tier 3 can give a conversation straight to a teammate.
  • Escalate it to Tier 2 or Tier 3 when it needs more access or experience, with a note on what you tried. It goes back to the queue, where only that tier and above can take it. Tier 1 and Tier 2 escalate only above their own tier. Tier 3 can lower an escalation, or clear it so any tier can take the conversation again.

The member you hand a conversation to must be able to answer it and have room under their claim limit. A change of holder ends any server access the conversation lent to the member who held it.

When you need to see a customer's server, ask the customer from the conversation. The conversation must be open and belong to a customer account, and a teammate must not hold it. Asking takes a conversation nobody holds for you.

  1. Choose the server. It must be one of this customer's.
  2. Ask for one of these, with a note of up to 500 characters that says why:
    • Logs, from Tier 1: latest shares logs/latest.log, and folder also shares up to 4 of the newest archived logs.
    • Server access, from Tier 2: basic gives the console, power and file access, and full gives everything a customer can give a subuser except reinstalling, restoring or deleting a snapshot or backup, and deleting a database.
  3. Wait for the customer to approve or decline the request in their conversation. Nothing is shared or granted until they approve, and a support session on their account cannot approve for them.

When the customer approves logs, we copy the files into the conversation as attachments from the customer. A file over 5 MB keeps its first 256 KB and its end, with a line that says how much we left out.

When the customer approves access, we add your storefront account to the server as a subuser, and the conversation says so. Your storefront account is the customer account the console signs you in to on your storefront. Unless an admin chose another, it is the one with your email, which we create the first time you sign in to the console. An admin can attach a different account or make you console-only, as Change a member's storefront account explains, and you need an active storefront account to ask for access. /staff/me lists the servers your storefront account can open, and lets you leave one. The access ends when:

  • the conversation closes;
  • you release it, or the conversation is released, escalated or goes to another member;
  • the customer removes it, or removes you from the server;
  • you move below Tier 2, or leave the team.

You can withdraw a request the customer has not answered. When sharing the logs or adding the subuser fails, the request says why and the customer can approve it again.

Escalate a conversation to Coritan

Section titled Escalate a conversation to Coritan

When your team needs us, Tier 3 can escalate a conversation to Coritan's support. We open a conversation on your own Coritan account, with the subject [Escalated] and the subject of the customer's conversation, and the customer's conversation shows a line with our conversation's number. Ours carries only that number and subject, so add what we need to know on your Coritan dashboard. The customer's conversation stays open in your inbox: keep the customer up to date there.

Open a conversation for a customer

Section titled Open a conversation for a customer

Tier 3 can start a conversation with a customer, after a phone call or about something your team noticed first. Give it a subject of up to 255 characters, your message, a priority and a department, and the order it is about if there is one. The customer sees a line saying that staff opened it for them, then your message, and we email it to them. The conversation is yours unless you choose otherwise, and the paid support rule below does not apply to it.

Save replies for common answers

Section titled Save replies for common answers

Open /staff/inbox/canned to see your organization's saved replies. Each has a title of up to 200 characters, a shortcut of up to 50, its text, and a department if it is for one. Tier 3 writes, changes and deletes them, and every member who can use the inbox can insert them.

Change many conversations at once

Section titled Change many conversations at once

Tier 3 can select up to 100 conversations in /staff/inbox and take them, drop them back into the queue, close them, or set their priority or department. We skip any conversation outside your organization.

Limit support to paying customers

Section titled Limit support to paying customers

Coritan can limit your organization's support to paying customers; the console and the dashboard have no switch for it, so contact support to turn it on or off. With it on:

  • anyone can write to the abuse, security, legal and sales departments;
  • a customer who has ever had an invoice above zero can write to billing and payments;
  • every other department needs a service that costs money.

A customer who may not open a conversation gets a message that says why, on your storefront, by email and in Discord alike. The rule does not apply to conversations your team opens.

The customer sees each reply and each change of status on their support page, and by email. The audit log records who took, passed on, escalated, changed and closed each conversation, and each request for logs or server access.

Support access required
Readonly members cannot use the inbox, and some actions need Tier 3. Ask an admin for a higher role.
Conversation not found
The conversation is not in your organization, or it is outside what your tier may read. Tier 1 reads only the queue and its own conversations.
This ticket belongs to another engineer; add an internal note, or ask Tier 3 to reassign it
A teammate holds the conversation. Leave them a note, or ask Tier 3 to give it to you.
This ticket was escalated to Tier 3
The conversation waits for a tier above yours.
409 with error set to claim_limit
You hold as many open conversations as Tier 1 may. Close or release one first. When you hand a conversation on, the message names the teammate whose limit it is.
Handing a ticket to a teammate is a transfer
Below Tier 3 you cannot assign a conversation to someone else. Transfer it instead.
Escalate to a tier above your own (Tier 1)
Tier 1 escalates to Tier 2 or Tier 3, and Tier 2 to Tier 3.
Take the ticket before asking the customer for anything
A teammate holds the conversation. Ask them, or have Tier 3 give it to you.
Asking for access to a customer's server is Tier 2 work
Tier 1 can ask for logs only. Escalate the conversation to Tier 2.
Server access is given to your own customer account on this brand, and you have none. An admin can link one on the Team page.
You have no storefront account, or it is not active. Ask an admin to attach one on /staff/team.
You already asked for that on this ticket
The same request still waits for the customer, or the access it asked for is still in place.
Reopen the ticket before asking the customer for anything
The conversation is closed. Reopen it first.
Only the customer can answer this. A support session cannot answer for them.
The customer must approve a request while signed in as themselves.
Customer not found in this organization
The customer ID is not one of your organization's customers.

The staff routes live under https://api.coritan.com/api/v1/orgs/{org_slug}/chat/staff/, and take a console session or a member's access token as The staff console explains. The customer routes live under /chat/conversations/ and /chat/meta, and take the customer's token. Staff support lists both, and your server access lists the two /staff/me/server-access routes.

Shell
curl -X POST "https://api.coritan.com/api/v1/orgs/acme/chat/staff/queue/take-next?audience=paid" \
  -H "Authorization: Bearer $STAFF_TOKEN"

It answers the conversation you now hold, or null when nobody is waiting. It also takes department. GET /chat/staff/queue lists the queue itself, with department, audience, page and limit 1–100 (20 by default).

Shell
curl "https://api.coritan.com/api/v1/orgs/acme/chat/staff/conversations?status=open&q=%231042" \
  -H "Authorization: Bearer $STAFF_TOKEN"

The list puts paying customers first, then the newest activity, and takes:

  • status: a status from Work the queue. open there means every status but closed.
  • priority: low, medium, high or critical.
  • q, up to 200 characters, matched against the subject, the last message, the customer's email and the number.
  • assigned_to_me, escalated, and for Tier 3 assigned_to with a member's user_id.
  • audience: paid, free or all.
  • page, and limit 1–100 (20 by default).

Each row has id, conversation_number, subject, status, priority, department, assigned_agent_id, assigned_agent_name, customer_id, user_email, channel, email_from, last_message_at, last_message_preview, tags, waiting_seconds, sla_first_response_due_at, sla_resolution_due_at, sla_breached_first_response, sla_breached_resolution, csat_score, is_free, viewers and escalated_tier. GET /chat/staff/stats takes audience and answers the figures above the inbox, with claim_limit and, for Tier 3, each member's open claims. GET /chat/staff/departments answers every department's slug, name and targets in minutes, and any member can read it.

Read and answer a conversation

Section titled Read and answer a conversation

GET /chat/staff/conversations/{conversation_id} answers the conversation with its messages, internal notes included. GET .../messages takes before_id and limit up to 100 (50 by default), and GET .../attachments/{attachment_id} downloads a file the customer attached.

Shell
curl -X POST https://api.coritan.com/api/v1/orgs/acme/chat/staff/conversations/5120/messages \
  -H "Authorization: Bearer $STAFF_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"body": "Your server is back online. Reply here if it stops again.", "close": true}'

body is 1–10,000 characters. client_request_id, up to 64 characters, makes a retry return the first message instead of sending a second one. Staff replies carry no attachments. POST .../internal-note takes a body of 1–10,000 characters, and POST .../viewing answers the other members who have the conversation open in viewers.

PATCH /chat/staff/conversations/{conversation_id} takes priority, department, status and, for Tier 3, customer_id. A status of closed closes the conversation, and any other status on a closed one reopens it. POST .../close and POST .../reopen do the same on their own. POST .../duplicate takes {"of": 5118}, the ID of the conversation to keep.

Assign, transfer, release and escalate

Section titled Assign, transfer, release and escalate
Route Body Who
POST .../assign {} to take it, or {"agent_id": 14} to give it Tier 1 takes; Tier 3 gives
POST .../transfer agent_id or department Tier 1
POST .../release optional note, up to 2,000 characters The holder, or Tier 3
POST .../escalate-tier tier 2 or 3, or null to clear; optional note Tier 1; clearing needs Tier 3
POST .../escalate none Tier 3

agent_id is a member's user_id, which GET /staff/team lists.

Shell
curl -X POST https://api.coritan.com/api/v1/orgs/acme/chat/staff/conversations/5120/requests \
  -H "Authorization: Bearer $STAFF_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"kind": "logs", "server_uuid": "3f6c2a9e-8b1d-4c57-9e02-5d7a41b8c613", "scope": "folder", "note": "The server stops a few minutes after it starts."}'

It answers 201 with the request. kind is logs, with scope latest or folder, or server_access, with scope basic or full. A request's status is pending, approved, declined, cancelled, failed or revoked. GET .../requests lists the conversation's requests, newest first and at most 50. POST .../requests/{request_id}/cancel withdraws one the customer has not answered, and POST .../requests/{request_id}/release, from Tier 2, gives back server access. Only the member who asked, or Tier 3, can do either.

GET /staff/me/server-access answers your linked customer_id and the servers your customer account is a subuser on, each with its permissions and, when a conversation lent it, via_ticket. POST /staff/me/server-access/{server_uuid}/leave answers {"ok": true} and ends that access.

POST /chat/staff/conversations takes customer_id, subject (1–255 characters), body (1–20,000), priority (medium by default), department (up to 50 characters), an optional service_id of the customer's, and assign_to_me (true by default). It answers 201 with the conversation.

Shell
curl -X POST https://api.coritan.com/api/v1/orgs/acme/chat/staff/conversations/bulk \
  -H "Authorization: Bearer $STAFF_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ids": [5120, 5121, 5133], "action": "priority", "value": "high"}'

action is assign_me, unassign, close, priority or department, and value holds the priority or department. It answers the action, how many IDs were requested, and how many changed.

GET /chat/staff/canned-responses lists saved replies, and with department only that department's and those with none. POST takes title, shortcut, body, department and is_shared, PUT /chat/staff/canned-responses/{response_id} changes any of them, and DELETE removes one. We store is_shared, but every member who can use the inbox reads every saved reply.

Build a customer's support page

Section titled Build a customer's support page

A storefront of your own calls the customer routes with the customer's token:

Shell
curl -X POST https://api.coritan.com/api/v1/orgs/acme/chat/conversations \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"subject": "Server will not start", "body": "It stops a few minutes after it starts.", "department": "technical", "priority": "high"}'

It answers 201 with the conversation. subject is up to 300 characters and body 1–10,000, with an optional service_id and client_request_id. GET /chat/meta answers what the form needs first: each department with whether this customer may write to it, the priorities, the attachment limits, and in access the reason a customer who may not open one reads.

Route What it does
GET /chat/conversations The customer's conversations, newest activity first. Takes status, priority, q, page and limit 1–100.
GET /chat/conversations/{conversation_id} and GET .../messages One conversation, without internal notes. messages takes before_id, after_id and limit up to 100.
POST .../messages A reply of 1–10,000 characters. A closed conversation answers 400 Conversation is closed, so reopen it first.
POST .../attachments One file as file, up to 25 MB, of a type GET /chat/meta lists.
POST .../read Marks our replies read, up to up_to_message_id when you send it.
POST .../close and POST .../reopen Closes or reopens the conversation.
POST .../csat A score of 1–5 and a comment of up to 500 characters, once the conversation is closed.
POST .../requests/{request_id}/approve, /decline and /revoke Answers a request for logs or access, or removes access given earlier.

A conversation that is not the customer's answers 403 Access denied.

API operations on this page

MethodPathWhat it does
GET/api/v1/orgs/{org_slug}/chat/conversationsList customer conversations
POST/api/v1/orgs/{org_slug}/chat/conversationsCreate customer conversation
GET/api/v1/orgs/{org_slug}/chat/conversations/{conversation_id}Get customer conversation
POST/api/v1/orgs/{org_slug}/chat/conversations/{conversation_id}/attachmentsUpload customer attachment
GET/api/v1/orgs/{org_slug}/chat/conversations/{conversation_id}/attachments/{attachment_id}Download customer attachment
GET/api/v1/orgs/{org_slug}/chat/conversations/{conversation_id}/attachments/{attachment_id}/thumbnailLets a thread show an image inline instead of a download link
POST/api/v1/orgs/{org_slug}/chat/conversations/{conversation_id}/closeClose customer conversation
POST/api/v1/orgs/{org_slug}/chat/conversations/{conversation_id}/csatRate customer conversation
GET/api/v1/orgs/{org_slug}/chat/conversations/{conversation_id}/messagesGet customer messages
POST/api/v1/orgs/{org_slug}/chat/conversations/{conversation_id}/messagesSend customer message
POST/api/v1/orgs/{org_slug}/chat/conversations/{conversation_id}/readMark customer conversation read
POST/api/v1/orgs/{org_slug}/chat/conversations/{conversation_id}/reopenReopen customer conversation
POST/api/v1/orgs/{org_slug}/chat/conversations/{conversation_id}/requests/{request_id}/approveApprove ticket request
POST/api/v1/orgs/{org_slug}/chat/conversations/{conversation_id}/requests/{request_id}/declineDecline ticket request
POST/api/v1/orgs/{org_slug}/chat/conversations/{conversation_id}/requests/{request_id}/revokeTake back access given from this ticket, before it closes
GET/api/v1/orgs/{org_slug}/chat/staff/canned-responsesList org canned responses
POST/api/v1/orgs/{org_slug}/chat/staff/canned-responsesCreate org canned response
PUT/api/v1/orgs/{org_slug}/chat/staff/canned-responses/{response_id}Update org canned response
DELETE/api/v1/orgs/{org_slug}/chat/staff/canned-responses/{response_id}Delete org canned response
GET/api/v1/orgs/{org_slug}/chat/staff/conversationsTickets, newest activity first
POST/api/v1/orgs/{org_slug}/chat/staff/conversationsOpen a ticket on a customer's behalf
POST/api/v1/orgs/{org_slug}/chat/staff/conversations/bulkBulk org staff conversations
GET/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}Get org staff conversation
PATCH/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}Priority, department, status, and (Tier 3 and above) which customer the ticket belongs to
POST/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/assignClaim a ticket, or with agentid (Tier 3 and above) give it to a teammate
GET/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/attachments/{attachment_id}The file a customer attached, for the staff member reading the ticket
POST/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/closeClose org staff conversation
POST/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/duplicateClose this ticket as a duplicate of another of the same customer's
POST/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/escalateEscalate org conversation
POST/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/escalate-tierPass a ticket up to Tier 2 or Tier 3, back into the queue there
POST/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/internal-noteA note for the desk, on any ticket the caller may read
GET/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/messagesGet org staff messages
POST/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/messagesA reply to a closed ticket reopens it first
POST/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/releaseGive a claimed ticket back to the queue
POST/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/reopenReopen org staff conversation
GET/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/requestsEvery request on the ticket, newest first, as its card shows it
POST/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/requestsCreate ticket request
POST/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/requests/{request_id}/cancelWithdraw a request the customer has not answered yet
POST/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/requests/{request_id}/releaseGive back server access before the ticket closes: done with it, or handing the work on
POST/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/transferTransfer org conversation
POST/api/v1/orgs/{org_slug}/chat/staff/conversations/{conversation_id}/viewingOrg ticket viewing
GET/api/v1/orgs/{org_slug}/chat/staff/departmentsDepartments with their names and SLAs, for anything staff-side that shows a ticket
GET/api/v1/orgs/{org_slug}/chat/staff/queueUnclaimed tickets waiting for an answer, at the caller's tier or below
POST/api/v1/orgs/{org_slug}/chat/staff/queue/take-nextClaim the ticket at the front of the queue and hand it back
GET/api/v1/orgs/{org_slug}/chat/staff/statsThe figures above the inbox, under the audience the request carries
GET/api/v1/orgs/{org_slug}/chat/metaGet customer support meta
GET/api/v1/orgs/{org_slug}/staff/me/server-accessMy server access
POST/api/v1/orgs/{org_slug}/staff/me/server-access/{server_uuid}/leaveStop being a subuser on a server