Link Codes#
Link codes enable users to connect their identities across multiple messaging platforms, creating a unified user profile.
Overview#
When a user contacts you on WhatsApp and later on Slack, they appear as two separate users. Link codes solve this by allowing users to prove they own both identities.
flowchart LR
subgraph Before["Before Linking"]
WA1["WhatsApp User<br/>+14155551234<br/>(User A)"]
SL1["Slack User<br/>U12345678<br/>(User B)"]
end
subgraph After["After Linking"]
subgraph Unified["Unified User"]
WA2["WhatsApp<br/>+14155551234"]
SL2["Slack<br/>U12345678"]
end
end
Before --> AfterHow Link Codes Work#
- User requests a link code on Platform A
- Outeract generates a unique code and sends it to the user
- User sends the code on Platform B
- Outeract validates and links the two platform users to the same user
Code Format#
Link codes follow a specific format for security and usability:
DDDD-DDDD-DDDD-CCCCExample: 1234-5678-9012-5924
- 16 numeric digits (0-9 only)
- Groups of 4 for readability
- Last group is a checksum (sum of first 3 groups mod 10000)
- Expires after a configurable time (default: 15 minutes)
Generating Link Codes#
GraphQL#
mutation GenerateLinkCode($platformUserId: UUID!) {
generateLinkCode(
platformUserId: $platformUserId
expiryMinutes: 15
maxUses: 1
) {
code
expiresAt
event {
id
eventType
}
}
}REST#
curl -X POST https://api.outeract.com/v1/link-codes \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"platform_user_id": "pu_abc123",
"expiry_minutes": 15,
"max_uses": 1
}'Response:
{
"code": "1234-5678-9012-5924",
"expires_at": "2024-01-15T10:45:00Z",
"event_id": "evt_linkcode123"
}Activating Link Codes#
Automatic Detection#
Enable automatic link code detection in your application settings:
mutation {
updateApplication(
config: {
link_code_auto_detect: "enabled"
}
) {
id
config
}
}When enabled, Outeract automatically detects link codes in incoming messages and processes them.
Manual Activation#
mutation ActivateLinkCode($code: String!, $platformUserId: UUID!) {
activateLinkCode(
code: $code
platformUserId: $platformUserId
) {
success
user {
id
platformUsers {
id
externalId
platformConnection {
platformName
}
}
}
}
}Link Code Events#
link_code.generated#
{
"event_type": "link_code.generated",
"payload": {
"code": "1234-5678-9012-5924",
"expiry_minutes": 15,
"max_uses": 1,
"uses": 0,
"generated_by_platform_user_id": "pu_abc123"
}
}link_code.activation#
{
"event_type": "link_code.activation",
"payload": {
"code": "1234-5678-9012-5924",
"source_platform_user_id": "pu_abc123",
"target_platform_user_id": "pu_xyz789",
"merged_user_id": "user_merged123"
}
}Implementation Example#
Bot Flow for Link Code Generation#
async def handle_link_request(message, platform_user_id):
# Generate link code
result = await client.execute("""
mutation GenerateLinkCode($platformUserId: UUID!) {
generateLinkCode(platformUserId: $platformUserId) {
code
expiresAt
}
}
""", {"platformUserId": platform_user_id})
code = result["generateLinkCode"]["code"]
expires = result["generateLinkCode"]["expiresAt"]
# Send to user
await send_message(
platform_user_id,
f"Your link code is: {code}\n\n"
f"Enter this code on your other platform to link accounts.\n"
f"This code expires in 15 minutes."
)Webhook Handler for Activation#
async def handle_webhook(event):
if event["event_type"] == "link_code.activation":
payload = event["payload"]
# Notify on source platform
await send_message(
payload["source_platform_user_id"],
"Your accounts have been linked successfully!"
)
# Notify on target platform
await send_message(
payload["target_platform_user_id"],
"Link code accepted! Your accounts are now connected."
)User Experience#
Requesting a Link Code#
User on WhatsApp:
User: "I want to link my Slack account"
Bot: "I'll generate a link code for you. Enter this code in Slack within 15 minutes:
1234-5678-9012-5924"Activating a Link Code#
User on Slack:
User: "1234-5678-9012-5924"
Bot: "Account linked! Your WhatsApp and Slack are now connected.
Messages from either platform will appear in your unified inbox."Configuration Options#
Code Expiry#
generateLinkCode(
platformUserId: $id
expiryMinutes: 30 # Default: 15
)Usage Limits#
generateLinkCode(
platformUserId: $id
maxUses: 3 # Default: 1
)Application-Level Settings#
{
"link_code_auto_detect": "enabled",
"link_code_default_expiry_minutes": 15,
"link_code_default_max_uses": 1
}Security Considerations#
1. Short Expiry Times#
Keep expiry times short (15-30 minutes) to reduce risk.
2. Single Use#
Default to single-use codes unless multi-use is needed.
3. Rate Limiting#
Limit code generation to prevent abuse:
# Built-in rate limit: 5 codes per user per hour4. Checksum Validation#
Codes include a checksum to prevent typos and brute-force attempts.
5. User Consent#
Always inform users what linking means:
- Unified message history
- Shared context across platforms
- Single user profile
Error Handling#
Invalid Code#
{
"error": "INVALID_LINK_CODE",
"message": "The link code is invalid or has expired"
}Expired Code#
{
"error": "LINK_CODE_EXPIRED",
"message": "This link code has expired. Please generate a new one."
}Already Used#
{
"error": "LINK_CODE_USED",
"message": "This link code has already been used."
}Self-Link Attempt#
{
"error": "SELF_LINK_ATTEMPT",
"message": "Cannot link a user to themselves."
}Querying Linked Users#
Get User with All Platform Identities#
query GetLinkedUser($userId: UUID!) {
user(id: $userId) {
id
name
platformUsers {
id
externalId
name
platformConnection {
id
platformName
name
}
createdAt
}
}
}Find User by Any Platform Identity#
query FindUserByPlatform($externalId: String!, $platformConnectionId: UUID!) {
platformUsers(
filters: {
externalId: { equals: $externalId }
platformConnectionId: { equals: $platformConnectionId }
}
) {
edges {
node {
user {
id
name
platformUsers {
externalId
platformConnection {
platformName
}
}
}
}
}
}
}Best Practices#
1. Clear Instructions#
Provide step-by-step instructions when generating codes.
2. Visual Formatting#
Format codes with dashes for readability: 1234-5678-9012-5924
3. Confirmation Messages#
Confirm successful linking on both platforms.
4. Handle Edge Cases#
- User already linked
- Expired codes
- Invalid format
5. Privacy Notice#
Explain what data will be shared between platforms before linking.