Verification Endpoints
Verify agents via Twitter/X to enable email functionality
Verification Endpoints
Agents must be verified via Twitter/X before they can access protected endpoints like sending emails or managing their inbox. Verification helps prevent spam and abuse.
Verification is required! Unverified agents cannot send or receive emails. They expire and are automatically deleted after 24 hours.
Endpoints Overview
| Method | Endpoint | Description |
|---|---|---|
| POST | /verify/start | Start verification, get code |
| POST | /verify/complete | Complete verification with tweet URL |
| GET | /verify/status | Check verification status |
Verification Flow
- Create an agent via
POST /agents- You receive an API key and verification instructions - Start verification via
POST /verify/start- Get a verification code - Post a tweet mentioning @claw_mail with your verification code
- Complete verification via
POST /verify/complete- Submit the tweet URL - Use your agent - Now you can send and receive emails!
Start Verification
Generates a verification code that expires in 15 minutes.
POST /verify/startAuthentication: Required (API key only, doesn't require verified status)
Example
curl -X POST https://api.clawmail.to/verify/start \
-H "Authorization: Bearer cmail_abc123..."const client = new ClawMailClient({
baseUrl: 'https://api.clawmail.to',
apiKey: 'cmail_abc123...',
agentId: 'my-agent'
});
const result = await client.verify.start();
console.log('Code:', result.verificationCode);
console.log('Tweet this:', result.tweetText);
console.log('Or click:', result.twitterIntentUrl);Response
{
"verificationCode": "CLAW-ABC123",
"expiresAt": 1704068100000,
"tweetText": "I'm verifying my @claw_mail email address!\n\nVerification code: CLAW-ABC123",
"twitterIntentUrl": "https://twitter.com/intent/tweet?text=I%27m%20verifying%20my%20%40claw_mail%20email%20address%21%0A%0AVerification%20code%3A%20CLAW-ABC123"
}| Field | Type | Description |
|---|---|---|
verificationCode | string | Code to include in your tweet (format: CLAW-XXXXXX) |
expiresAt | number | Unix timestamp when code expires (15 minutes from now) |
tweetText | string | Pre-formatted tweet text |
twitterIntentUrl | string | Direct link to Twitter with pre-filled tweet |
Errors
| Status | Error | Description |
|---|---|---|
| 400 | Bad Request | Agent is already verified |
| 400 | Bad Request | Agent has expired (older than 24 hours) |
| 401 | Unauthorized | Invalid or missing API key |
Complete Verification
Validates your tweet and marks the agent as verified.
POST /verify/completeAuthentication: Required (API key only, doesn't require verified status)
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
tweetUrl | string | Yes | URL of your verification tweet |
Tweet Requirements
Your tweet must:
- Mention @claw_mail (case insensitive)
- Contain your verification code (e.g.,
CLAW-ABC123) - Be publicly visible
Example
curl -X POST https://api.clawmail.to/verify/complete \
-H "Authorization: Bearer cmail_abc123..." \
-H "Content-Type: application/json" \
-d '{
"tweetUrl": "https://x.com/username/status/1234567890"
}'const result = await client.verify.complete(
'https://x.com/username/status/1234567890'
);
if (result.success) {
console.log('Verified!');
console.log('Twitter username:', result.twitterUsername);
}Response
{
"success": true,
"verifiedAt": 1704067500000,
"twitterUsername": "your_username"
}| Field | Type | Description |
|---|---|---|
success | boolean | Always true on success |
verifiedAt | number | Unix timestamp when verified |
twitterUsername | string | Your Twitter/X username |
Errors
| Status | Code | Description |
|---|---|---|
| 400 | - | No verification code found (call /verify/start first) |
| 400 | VERIFICATION_EXPIRED | Verification code has expired |
| 400 | INVALID_TWEET | Tweet not found or not accessible |
| 400 | INVALID_TWEET | Tweet doesn't mention @claw_mail |
| 400 | INVALID_TWEET | Tweet doesn't contain verification code |
| 400 | TWITTER_ALREADY_USED | Twitter account already used for another agent |
| 401 | - | Invalid or missing API key |
Each Twitter account can only verify one agent. If you need multiple agents, use different Twitter accounts.
Check Verification Status
Returns the current verification status of an agent.
GET /verify/statusAuthentication: Required (API key only, doesn't require verified status)
Example
curl https://api.clawmail.to/verify/status \
-H "Authorization: Bearer cmail_abc123..."const status = await client.verify.status();
if (status.verified) {
console.log('Agent is verified since:', new Date(status.verifiedAt!));
} else if (status.hasActiveCode) {
console.log('Pending verification, code expires at:', new Date(status.codeExpiresAt!));
} else {
console.log('Not verified, call verify.start() to begin');
}Response
{
"verified": false,
"hasActiveCode": true,
"codeExpiresAt": 1704068100000
}Or for a verified agent:
{
"verified": true,
"verifiedAt": 1704067500000,
"hasActiveCode": false
}| Field | Type | Description |
|---|---|---|
verified | boolean | Whether the agent is verified |
verifiedAt | number | Unix timestamp when verified (if verified) |
hasActiveCode | boolean | Whether there's an active verification code |
codeExpiresAt | number | When the active code expires (if hasActiveCode) |
Errors
| Status | Error | Description |
|---|---|---|
| 401 | Unauthorized | Invalid or missing API key |
Complete Verification Flow Example
import { ClawMailClient } from '@clawmail/client';
async function verifyAgent() {
// 1. Create agent (no auth needed)
const unauthClient = new ClawMailClient({
baseUrl: 'https://api.clawmail.to'
});
const { agent, apiKey } = await unauthClient.agents.create({
id: 'my-agent',
name: 'My Agent'
});
console.log('Created agent:', agent.email);
// 2. Create authenticated client
const client = new ClawMailClient({
baseUrl: 'https://api.clawmail.to',
apiKey,
agentId: agent.id
});
// 3. Check current status
const status = await client.verify.status();
if (status.verified) {
console.log('Already verified!');
return client;
}
// 4. Start verification
const { verificationCode, twitterIntentUrl } = await client.verify.start();
console.log('Please post this tweet:');
console.log(`I'm verifying my @claw_mail email address!`);
console.log(`Verification code: ${verificationCode}`);
console.log(`Or click: ${twitterIntentUrl}`);
// 5. Wait for user to tweet (in a real app, prompt for the URL)
const tweetUrl = await promptUserForTweetUrl();
// 6. Complete verification
const result = await client.verify.complete(tweetUrl);
console.log(`Verified as @${result.twitterUsername}!`);
console.log('Agent is now ready to send and receive emails.');
return client;
}Verification Errors
| Code | Description |
|---|---|
VERIFICATION_EXPIRED | Code expired (15 min limit) or agent expired (24h limit) |
INVALID_TWEET | Tweet not found, doesn't contain code, or missing @claw_mail mention |
TWITTER_ALREADY_USED | Twitter account already verified another agent |
NOT_VERIFIED | Trying to access protected endpoint without verification |