iMessage API on Windows for AI agents: Node.js setup
Build the part a Windows agent actually needs: one message out and one matching reply back into your process. The listener connects before the send, so delivery status never gets mistaken for a working thread.
Open the inbound listener from Node.js on Windows.
Use one phone you control for the first message.
Keep the process running until the reply appears.
Start with a 7-day trial
Get the API key for this Windows setup, then use one controlled phone to prove the complete two-way thread.
Start your 7-day trialThis is a developer tutorial, not a way to mirror your personal Messages inbox onto a PC. If you want a Windows chat client, compare the consumer options in the existing iMessage on Windows guide. Continue here if your Node.js agent or backend needs an iMessage API without maintaining Apple hardware.
What you need
- Windows 10 or 11 with PowerShell
- Node.js 22 or newer
- A Claw Messenger trial and API key beginning with
cm_live_ - One phone number you control, written in E.164 format
The trial signup asks you to choose a plan before setup. Keep the API key out of source control and use a controlled phone for this first thread.
1. Set the Windows environment
Open PowerShell in an empty project folder. Replace both placeholders; the phone number must include the country code.
$env:CLAW_API_KEY = "cm_live_YOUR_API_KEY"
$env:CONTROLLED_TEST_PHONE_E164 = "+1234567890"
node --versionExpected: Node prints v22 or newer. These variables last only for the current PowerShell session.
2. Register the controlled phone
Register the phone that will reply to the agent. Claw Messenger uses registered numbers to route inbound messages to the correct account.
$headers = @{ Authorization = "Bearer $env:CLAW_API_KEY" }
$body = @{ phone_number = $env:CONTROLLED_TEST_PHONE_E164 } | ConvertTo-Json
$request = @{
Method = "Post"
Uri = "https://claw-messenger.onrender.com/api/routes"
Headers = $headers
ContentType = "application/json"
Body = $body
}
Invoke-RestMethod @requestExpected: the response includes "ok": true.
3. Create the listener before you send
Save this as agent.mjs. It opens the WebSocket, confirms the connection is ready, then sends one plain message. Leaveservice unset so the relay can route automatically.
const apiKey = process.env.CLAW_API_KEY;
const testPhone = process.env.CONTROLLED_TEST_PHONE_E164;
if (!apiKey || !testPhone) {
throw new Error("Set CLAW_API_KEY and CONTROLLED_TEST_PHONE_E164 first.");
}
const socket = new WebSocket(
`wss://claw-messenger.onrender.com/ws?key=${encodeURIComponent(apiKey)}`
);
socket.addEventListener("open", async () => {
const response = await fetch(
"https://claw-messenger.onrender.com/api/agent/readiness",
{ headers: { Authorization: `Bearer ${apiKey}` } }
);
const readiness = await response.json();
if (!readiness.ready) {
console.error("Listener is not ready:", readiness.action);
socket.close();
return;
}
socket.send(JSON.stringify({
type: "send",
id: "windows-first-thread-1",
to: testPhone,
parts: [{
type: "text",
value: "Windows agent test. Reply yes in this thread."
}]
}));
console.log("Message sent. Keep this process running for the reply.");
});
socket.addEventListener("message", (event) => {
const data = JSON.parse(event.data);
if (data.type === "ping") {
socket.send(JSON.stringify({ type: "pong" }));
}
if (data.type === "send.result") {
console.log("Outbound result:", data);
}
if (data.type === "message") {
console.log("Reply received by your agent:", data.text);
}
});
socket.addEventListener("error", (error) => {
console.error("WebSocket error:", error);
});4. Run the Windows test
node .\agent.mjsWait for the outbound message, then reply yes from the same phone and thread. Keep PowerShell open until the matching inbound event prints.
That inbound event is the setup finish line.
An accepted, delivered, or read outbound result is useful, but it does not prove the agent can receive. If the reply arrives while the process is disconnected, restart agent.mjs; a saved matching reply returns after reconnect. The complete source of truth is the working-thread quickstart.
What to build next
Replace the fixed text with your agent call, but keep the same order: connect, check readiness, send, then wait for the matching reply. For framework-specific paths, use the published n8n, LangChain, or CrewAI packages linked from the docs.
Windows iMessage API questions
Can the agent run entirely on Windows?
Yes. The Node.js process, agent logic, and deployment can run on Windows. Claw Messenger manages the Apple-side relay.
Does this mirror my personal iMessage history?
No. Claw Messenger is an API for agents and automation, not a personal Windows Messages client.
Why connect before sending?
The live listener is what receives the reply. Connecting first avoids a false finish where the outbound message succeeds but the agent is not available for the inbound response.