Chat with your twin from your own software
The you2you API lets another app talk to your own digital twin: a Slack bot, a website widget, a script. Your app sends what people said, and your twin replies as it does in you2you.
Get a key
- Open you2you and go to Profile.
- Under Your digital twin, tap API keys, then New key.
- Name the key after the app that uses it, and copy it. You see it only once.
You can have up to 10 keys. Revoking one stops every app that uses it right away. A key only reaches your own twin. Keep it secret, like a password.
Send messages
Send the key as a bearer token. Pick your own id for each chat room. The room is created on the first message.
curl -X POST https://api.you2you.net/api/v1/chatrooms/support-42/messages \
-H "Authorization: Bearer y2y_..." \
-H "Content-Type: application/json" \
-d '{"messages": [{"type": "user", "name": "Ana", "message": "Hi! What do you do for fun?"}]}'
The answer is 202 {"status": "pending"}. Your twin replies in the background, usually within seconds.
- Send 1 to 20 messages at once, each up to 1,000 characters.
nameis who said it. Different names are different people to your twin, so it can join a group conversation.- Several posts in a row get one reply to all of them.
- A chat room id uses letters, digits and
. _ : -, up to 200 characters. It shows up in request logs, so don't put personal data in it.
Get the reply
Either ask for it:
curl "https://api.you2you.net/api/v1/chatrooms/support-42/messages?limit=2" \
-H "Authorization: Bearer y2y_..."
{
"status": "replied",
"detail": null,
"messages": [
{"type": "user", "name": "Ana", "message": "Hi! What do you do for fun?"},
{"type": "assistant", "name": "Suzy", "message": "Mostly hiking, and far too much baking."}
]
}
Or have it sent to you: add "callback_url": "https://..." to the POST. When the turn ends, we POST {chatroom_id, status, detail, messages} to that URL. messages is empty unless the status is replied. A room uses the latest URL you sent.
Callbacks are not signed. Put a user and password in the URL (https://user:secret@example.com/hook) and check them on your side: we send them as Basic auth. We try 3 times, wait 5 seconds at most and don't follow redirects.
Examples
Each example goes through the whole flow: it sends a message and waits for the reply, sends a second one from another person, reads the conversation, lists your chat rooms and deletes the room. Set Y2Y_API_KEY in your environment first. Run them on your own computer or server: never put a key in a web page or a mobile app.
Needs curl and jq. Save it as ask.sh and run bash ask.sh.
#!/usr/bin/env bash
set -euo pipefail
API=https://api.you2you.net/api/v1/chatrooms
ROOM=example-1
AUTH="Authorization: Bearer $Y2Y_API_KEY"
# Send one message and wait until your twin's turn ends.
send() {
jq -n --arg name "$1" --arg message "$2" '{messages: [{type: "user", name: $name, message: $message}]}' |
curl -fsS -X POST "$API/$ROOM/messages" -H "$AUTH" -H "Content-Type: application/json" -d @- > /dev/null
while true; do
sleep 2
body=$(curl -fsS "$API/$ROOM/messages?limit=1" -H "$AUTH")
[ "$(jq -r .status <<< "$body")" != pending ] && break
done
jq -r 'if .status == "replied" then "Twin: \(.messages[-1].message)" else "No reply (\(.status)): \(.detail)" end' <<< "$body"
}
# 1. The first message creates the room.
send Ana "Hi! What do you do for fun?"
# 2. Keep talking in the same room. Another name is another person.
send Ben "And what is your favourite book?"
# 3. Read the conversation, oldest first.
curl -fsS "$API/$ROOM/messages?limit=50" -H "$AUTH" | jq -r '.messages[] | "\(.name): \(.message)"'
# 4. List your chat rooms, most recently active first.
curl -fsS "$API?limit=20" -H "$AUTH" | jq -r '.items[] | "\(.chatroom_id) \(.status) \(.message_count)"'
# 5. Delete the room.
curl -fsS -X DELETE "$API/$ROOM" -H "$AUTH"
Needs pip install requests. Save it as ask.py and run python ask.py.
import os
import time
import requests
API = "https://api.you2you.net/api/v1/chatrooms"
ROOM = "example-1"
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['Y2Y_API_KEY']}"
def send(name, message):
"""Send one message and wait until your twin's turn ends."""
session.post(
f"{API}/{ROOM}/messages",
json={"messages": [{"type": "user", "name": name, "message": message}]},
).raise_for_status()
while True:
time.sleep(2)
response = session.get(f"{API}/{ROOM}/messages", params={"limit": 1})
response.raise_for_status()
body = response.json()
if body["status"] != "pending":
break
if body["status"] == "replied":
print("Twin:", body["messages"][-1]["message"])
else:
print(f"No reply ({body['status']}):", body["detail"])
# 1. The first message creates the room.
send("Ana", "Hi! What do you do for fun?")
# 2. Keep talking in the same room. Another name is another person.
send("Ben", "And what is your favourite book?")
# 3. Read the conversation, oldest first.
history = session.get(f"{API}/{ROOM}/messages", params={"limit": 50})
history.raise_for_status()
for message in history.json()["messages"]:
print(f"{message['name']}: {message['message']}")
# 4. List your chat rooms, most recently active first.
rooms = session.get(API, params={"limit": 20})
rooms.raise_for_status()
for room in rooms.json()["items"]:
print(room["chatroom_id"], room["status"], room["message_count"])
# 5. Delete the room.
session.delete(f"{API}/{ROOM}").raise_for_status()
Needs Node 18 or newer. Save it as ask.mjs and run node ask.mjs.
const API = "https://api.you2you.net/api/v1/chatrooms";
const ROOM = "example-1";
const headers = {
Authorization: `Bearer ${process.env.Y2Y_API_KEY}`,
"Content-Type": "application/json",
};
async function call(method, url, body) {
const response = await fetch(url, { method, headers, body: body && JSON.stringify(body) });
if (!response.ok) throw new Error(`${method} ${url} failed with ${response.status}`);
return response.status === 204 ? null : response.json();
}
// Send one message and wait until your twin's turn ends.
async function send(name, message) {
await call("POST", `${API}/${ROOM}/messages`, { messages: [{ type: "user", name, message }] });
let body;
do {
await new Promise((resolve) => setTimeout(resolve, 2000));
body = await call("GET", `${API}/${ROOM}/messages?limit=1`);
} while (body.status === "pending");
if (body.status === "replied") console.log("Twin:", body.messages.at(-1).message);
else console.log(`No reply (${body.status}):`, body.detail);
}
// 1. The first message creates the room.
await send("Ana", "Hi! What do you do for fun?");
// 2. Keep talking in the same room. Another name is another person.
await send("Ben", "And what is your favourite book?");
// 3. Read the conversation, oldest first.
const history = await call("GET", `${API}/${ROOM}/messages?limit=50`);
for (const message of history.messages) console.log(`${message.name}: ${message.message}`);
// 4. List your chat rooms, most recently active first.
const rooms = await call("GET", `${API}?limit=20`);
for (const room of rooms.items) console.log(room.chatroom_id, room.status, room.message_count);
// 5. Delete the room.
await call("DELETE", `${API}/${ROOM}`);
Statuses
| Status | Means |
|---|---|
pending | Your twin is still working on it. |
replied | Your twin answered. |
no_reply | Your twin chose not to answer, or its answer was held back. |
over_budget | Your monthly AI budget is spent. |
paused | Your account or your twin is paused in the app. |
failed | Something went wrong on our side. Try again later. |
When you can do something about it, detail says why in plain words.
All routes
| Route | Does |
|---|---|
POST /api/v1/chatrooms/{id}/messages | Adds messages, creating the room if needed. |
GET /api/v1/chatrooms/{id}/messages?limit=1 | The status and the newest 1 to 50 messages, oldest first. |
GET /api/v1/chatrooms?limit=20&offset=0 | Your rooms as {items, total}, most recently active first. |
DELETE /api/v1/chatrooms/{id} | Deletes a room. Posting to the same id later starts an empty one. |
The full reference is at api.you2you.net/api/v1/docs, and the OpenAPI schema at api.you2you.net/api/v1/openapi.json.
Errors and limits
401: the key is wrong or revoked.404: no chat room has that id.409: your twin is not ready yet, or is deactivated.422: the request is not valid. The body says which field.429: too many requests. Each key may post 60 times a minute.
Replies use the same monthly AI budget as your twin in the app, across all your keys.
Your data
These chat rooms don't appear in the app. They are part of your data export. Revoking a key keeps its rooms; deleting your account deletes them and your keys. Details are in our Privacy Policy. Questions: info@you2you.net.