API Reference

Control your email, calendar, and LinkedIn from any AI client or your own code.

Last updated July 2026

Quick Start

Two ways to connect. Pick whichever fits your workflow.

MCP Server

Add to Claude Desktop, Cursor, or any MCP client. Your AI gets 28 tools instantly.

claude_desktop_config.json
{
  "mcpServers": {
    "eaai": {
      "url": "https://eaai.io/api/mcp",
      "headers": {
        "Authorization": "Bearer sk_eaai_..."
      }
    }
  }
}

Prompt API

One REST endpoint. Send a question, get an answer with real data from your accounts.

bash
curl -X POST https://eaai.io/api/v1/prompt \
  -H "Authorization: Bearer sk_eaai_..." \
  -H "Content-Type: application/json" \
  -d '{"prompt": "What meetings do I have tomorrow?"}'

Authentication

All API requests require a Bearer token in the Authorization header.

Authorization: Bearer sk_eaai_YOUR_API_KEY

Create API keys in your EA AI dashboard. Each key has a scope that controls what it can do.

read

Read-only access to all tools. Mutations are blocked.

approve

Read access plus mutations that queue for your approval in the dashboard.

full

Direct execution of all tools. Use for trusted, fully autonomous automation.

Scopes & Permissions

What each scope level can do across all 28 tools.

Toolreadapprovefull
Emaillist_emails
get_email
search_emails
send_email
reply_to_email
Calendarlist_events
get_event
check_availability
create_event
update_event
delete_event
LinkedInlist_linkedin_conversations
get_linkedin_conversation
mark_linkedin_read*
send_linkedin_message
reply_linkedin_message
get_linkedin_profile
list_linkedin_connections
search_linkedin
list_linkedin_invitations
send_linkedin_invitation
accept_linkedin_invitation*
withdraw_linkedin_invitation
list_linkedin_posts
get_linkedin_post
create_linkedin_post
comment_linkedin_post
react_linkedin_post*
Allowed Queued for approval Blocked

* mark_linkedin_read, accept_linkedin_invitation, and react_linkedin_post are low-risk mutations allowed under the approve scope without requiring approval.

The notetaker joins your video calls and writes them up on every plan, and you can ask about any meeting in EA AI chat. Meeting notes are not reachable from the API or the MCP server yet.

Rate Limits

LimitValueResponse
Requests per minute60429 Too Many Requests
Daily mutation capConfigurable per keyBlocked with reason
Recipient domain allowlistConfigurable per keyBlocked (send_email only)

The daily mutation cap and recipient domain allowlist are optional safety guards you can set when creating an API key.

LinkedIn Safety Limits

EA AI enforces per-account rate limits on every LinkedIn action to keep your account safe. These limits mirror the behavior of a careful human user and prevent triggering LinkedIn's anti-automation detection.

Daily Limits

ActionDaily LimitMin. Gap
New messages25~45s
Replies80~30s
Connection requests20~60s
Posts3~120s
Comments15~45s
Reactions30~10s
Searches30~15s
Profile views80~10s
Total actions (all types)150-

Daily limits reset at midnight UTC. Min. gap values are randomized (0.5x to 1.5x) to mimic natural human timing.

Weekly Limits

ActionWeekly LimitWindow
Connection requests100Rolling 7 days

Account Warm-up

Newly connected LinkedIn accounts enter a 28-day warm-up with gradually increasing limits. This mirrors industry best practices (Expandi, Dux-Soup) to prevent triggering LinkedIn's detection.

Week 1

20% of normal limits. Establish a baseline with mostly organic activity.

Week 2

40% of limits. Light automated activity begins alongside organic use.

Week 3

70% of limits. Ramping toward full capacity with proven account health.

Week 4+

100% capacity. Fully warmed up and operating at normal limits.

Natural Behavior Pacing

Every LinkedIn action is spaced with randomized delays. If your AI agent sends actions too quickly, the API returns a pacing error with a retry_after_seconds value. The AI client should wait and retry automatically.

Pacing response (HTTP 200, tool error)
{
  "error": "Pacing: wait 12s before the next LinkedIn message send action.",
  "retry_after_seconds": 12,
  "hint": "Wait before retrying. This pacing protects the LinkedIn account from detection.",
  "linkedin_safety": {
    "category": "message_send",
    "daily_usage": "5/30",
    "warmup_phase": "full"
  }
}

Activity Dashboard

Use the get_linkedin_activity tool or the REST endpoint to check your current usage at any time.

REST endpoint
GET https://eaai.io/api/v1/linkedin/activity
Authorization: Bearer sk_eaai_...

After every LinkedIn mutation, the response also includes a linkedin_safety field showing current usage for that action category.

MCP Server

EA AI exposes a Model Context Protocol server using Streamable HTTP transport. Add it to any MCP-compatible client.

Endpoint

https://eaai.io/api/mcp

Claude Desktop

claude_desktop_config.json
{
  "mcpServers": {
    "eaai": {
      "url": "https://eaai.io/api/mcp",
      "headers": {
        "Authorization": "Bearer sk_eaai_..."
      }
    }
  }
}

Cursor

.cursor/mcp.json
{
  "mcpServers": {
    "eaai": {
      "type": "streamable-http",
      "url": "https://eaai.io/api/mcp",
      "headers": {
        "Authorization": "Bearer sk_eaai_..."
      }
    }
  }
}

Supported methods

The server supports tools/list and tools/call over POST (JSON-RPC). Sessions are stateless.

Prompt API

A single REST endpoint. Send a natural-language prompt and EA AI runs a tool loop (up to 10 turns) to answer using your connected accounts.

Endpoint

POST https://eaai.io/api/v1/prompt

Request

json
{
  "prompt": "What meetings do I have tomorrow?"
}

Response

json
{
  "response": "You have 3 meetings tomorrow:\n\n1. 9:00 AM - Team standup (Google Meet)\n2. 11:30 AM - Product review with Sarah\n3. 2:00 PM - Client call with Acme Corp",
  "usage": {
    "input_tokens": 1542,
    "output_tokens": 387
  }
}

Parameters

ParameterTypeDescription
promptstringNatural-language request. EA AI determines which tools to call.

Errors

All errors return JSON with an error field.

{ "error": "Unauthorized" }
StatusMeaning
400Bad request. The prompt field is missing or not a string.
401Invalid, revoked, or missing API key.
429Rate limit exceeded. Wait and retry.

When a tool call is blocked by scope enforcement (e.g., a mutation on a read-scoped key), the error is returned within the response text, not as an HTTP error.

Tool Reference Required parameterread Read-onlymutation Writes data

Email Tools

Read, search, send, and reply to emails across Gmail and Outlook.

list_emailsread

List recent email threads. Optionally filter to unread only or by sender name/email.

Parameters

ParameterTypeDescription
limitnumberMax threads to return (default 20, max 50).
unread_onlybooleanOnly return unread threads.
from_filterstringFilter by participant name or email (case-insensitive partial match).

Response

[
  {
    "id": "a1b2c3d4-...",
    "subject": "Q3 budget review",
    "from": "Sarah Chen <sarah@example.com>",
    "date": "2026-06-30T14:22:00.000Z",
    "source": "gmail"
  }
]
get_emailread

Get full thread details and all messages for a given thread ID.

Parameters

ParameterTypeDescription
thread_idstringThe thread ID to retrieve.

Response

{
  "thread": {
    "id": "a1b2c3d4-...",
    "subject": "Q3 budget review"
  },
  "messages": [
    {
      "from": "Sarah Chen <sarah@example.com>",
      "body": "Hi, attached is the Q3 budget...",
      "date": "2026-06-30T14:22:00.000Z",
      "outbound": false
    }
  ]
}
search_emailsread

Search email threads by subject, participant name, or participant email.

Parameters

ParameterTypeDescription
querystringSearch term to match against subject, name, or email.
limitnumberMax results (default 10, max 20).

Response

[
  {
    "id": "a1b2c3d4-...",
    "subject": "Q3 budget review",
    "from": "Sarah Chen <sarah@example.com>",
    "date": "2026-06-30T14:22:00.000Z",
    "source": "gmail"
  }
]
send_emailmutation

Send a new email via your connected email account. Subject to domain allowlist if configured on the API key.

Parameters

ParameterTypeDescription
tostringRecipient email address.
subjectstringEmail subject line.
bodystringEmail body (plain text or HTML).
from_emailstringSender address (if the connector supports aliases).

Response

{
  "success": true,
  "provider": "gmail",
  "messageId": "msg_abc123"
}
reply_to_emailmutation

Reply to the most recent inbound message in an existing email thread. Replies bypass the domain allowlist.

Parameters

ParameterTypeDescription
thread_idstringThe thread ID to reply in.
bodystringReply body (plain text or HTML).

Response

{
  "success": true,
  "messageId": "msg_def456"
}

Calendar Tools

List, create, update, and delete events across Google Calendar, Microsoft Calendar, and CalDAV.

list_eventsread

List calendar events across all connected calendars within a date range, sorted by start time.

Parameters

ParameterTypeDescription
start_datestringStart date in ISO format (e.g. 2026-07-01).
end_datestringEnd date in ISO format (e.g. 2026-07-02).

Response

[
  {
    "id": "evt_abc123",
    "title": "Team standup",
    "start": "2026-07-01T09:00:00.000Z",
    "end": "2026-07-01T09:30:00.000Z",
    "location": "Google Meet",
    "attendees": ["alice@example.com"],
    "source": "google_calendar",
    "account": "you@example.com"
  }
]
get_eventread

Get full details of a specific calendar event by its ID. Currently fully supported for Google Calendar.

Parameters

ParameterTypeDescription
event_idstringThe event ID to retrieve.
calendar_idstringCalendar ID (defaults to account email).
sourcestringSource filter: google_calendar, microsoft_calendar, or caldav.
check_availabilityread

Check busy/free status across all connected calendars for a given time range.

Parameters

ParameterTypeDescription
start_datestringStart of range in ISO format.
end_datestringEnd of range in ISO format.

Response

{
  "busy": [
    {
      "start": "2026-07-01T09:00:00.000Z",
      "end": "2026-07-01T09:30:00.000Z",
      "calendarId": "you@example.com"
    }
  ]
}
create_eventmutation

Create a new calendar event. Uses the first connected Google Calendar by default.

Parameters

ParameterTypeDescription
titlestringEvent title.
startstringStart time in ISO format.
endstringEnd time in ISO format.
descriptionstringEvent description.
attendeesstring[]List of attendee email addresses.
locationstringEvent location.

Response

{
  "eventId": "evt_new123",
  "title": "Product review",
  "start": "2026-07-02T14:00:00.000Z",
  "end": "2026-07-02T15:00:00.000Z"
}
update_eventmutation

Update an existing calendar event. Only provided fields are changed. Requires Google Calendar.

Parameters

ParameterTypeDescription
event_idstringThe event ID to update.
calendar_idstringCalendar ID (defaults to account email).
titlestringNew event title.
startstringNew start time in ISO format.
endstringNew end time in ISO format.
descriptionstringNew event description.
attendeesstring[]Updated list of attendee email addresses.
locationstringNew event location.

Response

{
  "success": true,
  "eventId": "evt_abc123"
}
delete_eventmutation

Delete a calendar event by its ID. Requires Google Calendar.

Parameters

ParameterTypeDescription
event_idstringThe event ID to delete.
calendar_idstringCalendar ID (defaults to account email).

Response

{
  "success": true,
  "eventId": "evt_abc123"
}

LinkedIn Tools

Full LinkedIn support: messaging, profiles, connections, invitations, and posts.

Messaging

list_linkedin_conversationsread

List recent LinkedIn conversations. When multiple LinkedIn accounts are connected, aggregates across all unless filtered.

Parameters

ParameterTypeDescription
limitnumberMax conversations per account (default 20, max 50).
account_emailstringScope to a specific LinkedIn account.

Response

{
  "account": "you@example.com",
  "conversations": [
    {
      "id": "conv_abc123",
      "participant": "Alex Kim",
      "lastMessageAt": "2026-06-30T16:45:00.000Z"
    }
  ]
}
get_linkedin_conversationread

Get full message history for a LinkedIn conversation. Auto-resolves which connected account owns the conversation.

Parameters

ParameterTypeDescription
conversation_idstringThe conversation ID to retrieve.
account_emailstringLinkedIn account to use (auto-resolved if omitted).

Response

{
  "account": "you@example.com",
  "conversation": {
    "id": "conv_abc123",
    "participant": "Alex Kim"
  },
  "messages": [
    {
      "body": "Hey, are you free for a call this week?",
      "sender": "Alex Kim",
      "date": "2026-06-30T16:45:00.000Z",
      "outbound": false
    }
  ]
}
mark_linkedin_readmutation

Mark a LinkedIn conversation as read. Low-risk mutation allowed even under the approve scope without approval.

Parameters

ParameterTypeDescription
conversation_idstringThe conversation ID to mark as read.
account_emailstringLinkedIn account (auto-resolved if omitted).

Response

{
  "success": true,
  "account": "you@example.com"
}
send_linkedin_messagemutation

Send a new LinkedIn message to a recipient, starting a new conversation. When multiple accounts are connected, account_email is required.

Parameters

ParameterTypeDescription
recipient_idstringLinkedIn profile ID or URN of the recipient.
messagestringMessage body to send.
account_emailstringLinkedIn account to send from (required if multiple accounts).

Response

{
  "success": true,
  "chat_id": "conv_new456",
  "account": "you@example.com"
}
reply_linkedin_messagemutation

Reply to an existing LinkedIn conversation. Auto-resolves which connected account owns the conversation.

Parameters

ParameterTypeDescription
conversation_idstringThe conversation ID to reply in.
messagestringReply message body.
account_emailstringLinkedIn account to reply from (auto-resolved if omitted).

Response

{
  "success": true,
  "messageId": "msg_li_789",
  "account": "you@example.com"
}

Profiles & Search

get_linkedin_profileread

Get a LinkedIn profile by identifier (profile URN, LinkedIn URL, or vanity name). Returns name, headline, location, company, and connection degree.

Parameters

ParameterTypeDescription
identifierstringLinkedIn profile URN, URL, or vanity name.
account_emailstringLinkedIn account to use (optional).

Response

{
  "account": "you@example.com",
  "profile": {
    "id": "urn:li:person:abc123",
    "name": "Sarah Chen",
    "headline": "VP Engineering at Acme Corp",
    "location": "San Francisco, CA",
    "company": "Acme Corp",
    "connectionDegree": "2nd"
  }
}
list_linkedin_connectionsread

List LinkedIn connections (1st-degree relations) for the connected account.

Parameters

ParameterTypeDescription
limitnumberMax connections to return (default 50).
account_emailstringLinkedIn account to use (optional).

Response

{
  "account": "you@example.com",
  "connections": [
    {
      "id": "urn:li:person:def456",
      "name": "Alex Kim",
      "headline": "Product Manager",
      "company": "TechCo"
    }
  ]
}
search_linkedinread

Search LinkedIn profiles by keyword query. Returns matching profiles with name, headline, company, and connection degree.

Parameters

ParameterTypeDescription
querystringSearch query (name, title, company, keywords).
limitnumberMax results (default 20).
account_emailstringLinkedIn account to use (optional).

Response

{
  "account": "you@example.com",
  "results": [
    {
      "id": "urn:li:person:ghi789",
      "name": "Jordan Lee",
      "headline": "CTO at StartupXYZ",
      "company": "StartupXYZ",
      "connectionDegree": "3rd"
    }
  ]
}

Invitations

list_linkedin_invitationsread

List pending LinkedIn connection requests (both sent and received).

Parameters

ParameterTypeDescription
account_emailstringLinkedIn account (optional).

Response

{
  "account": "you@example.com",
  "invitations": [
    {
      "id": "inv_abc123",
      "direction": "received",
      "providerName": "Pat Taylor",
      "message": "I'd love to connect!"
    }
  ]
}
send_linkedin_invitationmutation

Send a LinkedIn connection request to a person. Optionally include a personalized message.

Parameters

ParameterTypeDescription
provider_idstringLinkedIn profile URN of the person to connect with.
messagestringOptional personalized connection message (max 300 chars).
account_emailstringLinkedIn account to send from (required if multiple accounts).

Response

{
  "success": true,
  "invitation_id": "inv_new789",
  "account": "you@example.com"
}
accept_linkedin_invitationmutation

Accept a received LinkedIn connection request. Low-risk mutation allowed under the approve scope without approval.

Parameters

ParameterTypeDescription
invitation_idstringThe invitation ID to accept.
account_emailstringLinkedIn account (optional).

Response

{
  "success": true,
  "account": "you@example.com"
}
withdraw_linkedin_invitationmutation

Withdraw a sent LinkedIn connection request.

Parameters

ParameterTypeDescription
invitation_idstringThe invitation ID to withdraw.
account_emailstringLinkedIn account (optional).

Response

{
  "success": true,
  "account": "you@example.com"
}

Posts & Engagement

list_linkedin_postsread

List LinkedIn posts by a user or company. If no identifier provided, lists your own posts.

Parameters

ParameterTypeDescription
identifierstringProfile URN to list posts for (omit for own posts).
limitnumberMax posts to return (default 20).
account_emailstringLinkedIn account (optional).

Response

{
  "account": "you@example.com",
  "posts": [
    {
      "id": "post_abc123",
      "authorName": "You",
      "text": "Excited to announce our new product launch...",
      "createdAt": "2026-06-28T10:00:00.000Z",
      "likeCount": 47,
      "commentCount": 12
    }
  ]
}
get_linkedin_postread

Get a LinkedIn post by ID, including its comments.

Parameters

ParameterTypeDescription
post_idstringThe post ID.
account_emailstringLinkedIn account (optional).

Response

{
  "account": "you@example.com",
  "post": {
    "id": "post_abc123",
    "authorName": "Sarah Chen",
    "text": "Great insights on AI in healthcare...",
    "likeCount": 23,
    "commentCount": 5
  },
  "comments": [
    {
      "id": "cmt_def456",
      "authorName": "Alex Kim",
      "text": "Totally agree with this take!"
    }
  ]
}
create_linkedin_postmutation

Create a new LinkedIn post as the connected user.

Parameters

ParameterTypeDescription
textstringPost text content.
account_emailstringLinkedIn account to post from (required if multiple).

Response

{
  "success": true,
  "post_id": "post_new789",
  "account": "you@example.com"
}
comment_linkedin_postmutation

Comment on a LinkedIn post.

Parameters

ParameterTypeDescription
post_idstringThe post ID to comment on.
textstringComment text.
account_emailstringLinkedIn account (optional).

Response

{
  "success": true,
  "comment_id": "cmt_new012",
  "account": "you@example.com"
}
react_linkedin_postmutation

React to a LinkedIn post. Low-risk mutation allowed under the approve scope without approval.

Parameters

ParameterTypeDescription
post_idstringThe post ID to react to.
reaction_typestringReaction type: LIKE, CELEBRATE, SUPPORT, LOVE, INSIGHTFUL, or FUNNY.
account_emailstringLinkedIn account (optional).

Response

{
  "success": true,
  "account": "you@example.com"
}

Activity Dashboard

get_linkedin_activityread

View your LinkedIn activity dashboard: daily usage vs. safety limits, warm-up status, weekly invitation quota, and recent actions. Use to monitor remaining capacity.

Response

{
  "connectedAt": "2026-06-15T10:30:00.000Z",
  "warmup": {
    "phase": "full",
    "daysConnected": 18,
    "daysRemaining": 0,
    "multiplier": 1
  },
  "categories": [
    {
      "category": "message_send",
      "label": "Messages sent",
      "used": 5, "limit": 30, "pct": 17
    },
    {
      "category": "invitation_send",
      "label": "Connection requests",
      "used": 12, "limit": 20, "pct": 60
    }
  ],
  "weeklyInvitations": {
    "used": 45, "limit": 100, "pct": 45
  },
  "recentActions": [
    {
      "tool": "reply_linkedin_message",
      "category": "message_reply",
      "at": "2026-07-03T14:22:00Z",
      "status": "ok"
    }
  ]
}