[{"data":1,"prerenderedAt":961},["ShallowReactive",2],{"navigation":3,"page:\u002Fsdks":45},{"title":4,"links":5},"API reference",[6,9,12,15,18,21,24,27,30,33,36,39,42],{"title":7,"href":8},"Accounts","\u002Freference\u002Faccounts",{"title":10,"href":11},"Connect","\u002Freference\u002Fconnect",{"title":13,"href":14},"Calendars","\u002Freference\u002Fcalendars",{"title":16,"href":17},"Events","\u002Freference\u002Fevents",{"title":19,"href":20},"Availability","\u002Freference\u002Favailability",{"title":22,"href":23},"Meetings","\u002Freference\u002Fmeetings",{"title":25,"href":26},"Invitations","\u002Freference\u002Finvitations",{"title":28,"href":29},"Webhooks","\u002Freference\u002Fwebhooks",{"title":31,"href":32},"Metadata","\u002Freference\u002Fmetadata",{"title":34,"href":35},"Keys","\u002Freference\u002Fkeys",{"title":37,"href":38},"Sandbox","\u002Freference\u002Fsandbox",{"title":40,"href":41},"Usage","\u002Freference\u002Fusage",{"title":43,"href":44},"Logs","\u002Freference\u002Flogs",{"kind":46,"title":47,"description":48,"sections":49,"doc":74},"guide","SDKs and tools","The Node.js SDK, the CLI, the Postman collection, the MCP server and AI tools, and PyasConnect for your frontend.",[50,53,56,59,62,65,68,71],{"id":51,"title":52},"official-libraries","Official libraries",{"id":54,"title":55},"nodejs-and-typescript","Node.js and TypeScript",{"id":57,"title":58},"the-cli","The CLI",{"id":60,"title":61},"postman","Postman",{"id":63,"title":64},"mcp-server","MCP server",{"id":66,"title":67},"ai-tools-for-your-app","AI tools for your app",{"id":69,"title":70},"pyasconnect","PyasConnect",{"id":72,"title":73},"for-coding-agents","For coding agents",{"id":75,"title":47,"body":76,"description":48,"extension":952,"hero":953,"meta":954,"navigation":166,"path":955,"rawbody":956,"sections":49,"seo":957,"stem":958,"v1":959,"__hash__":960},"docs\u002Fsdks.md",{"type":77,"value":78,"toc":943},"minimark",[79,83,98,101,104,112,137,243,266,312,314,333,530,552,559,588,590,600,629,635,637,645,651,687,690,793,800,802,812,826,828,868,885,887,939],[80,81,47],"h1",{"id":82},"sdks-and-tools",[84,85,86],"lead",{},[87,88,89,90,97],"p",{},"The Pyas API uses plain HTTPS and JSON, and an ",[91,92,96],"a",{"href":93,"rel":94},"https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fopenapi.json",[95],"nofollow","OpenAPI document"," describes every endpoint. The tools on this page make common tasks quicker for you and for your coding agent.",[99,100],"libraries",{},[102,103,55],"h2",{"id":54},[87,105,106,107,111],{},"The types in ",[108,109,110],"code",{},"@pyas\u002Fsdk"," are generated from the OpenAPI document, so your editor can autocomplete every field. The SDK requires Node 20 or later and has no dependencies.",[113,114,119],"pre",{"className":115,"code":116,"language":117,"meta":118,"style":118},"language-bash shiki shiki-themes css-variables","npm install @pyas\u002Fsdk\n","bash","",[108,120,121],{"__ignoreMap":118},[122,123,126,130,134],"span",{"class":124,"line":125},"line",1,[122,127,129],{"class":128},"s1IGz","npm",[122,131,133],{"class":132},"sTB4W"," install",[122,135,136],{"class":132}," @pyas\u002Fsdk\n",[113,138,142],{"className":139,"code":140,"language":141,"meta":118,"style":118},"language-js shiki shiki-themes css-variables","import { Pyas } from '@pyas\u002Fsdk'\n\nconst pyas = new Pyas({ apiKey: process.env.PYAS_API_KEY })\nconst event = await pyas.events.get({ accountId, eventId })\n","js",[108,143,144,161,168,210],{"__ignoreMap":118},[122,145,146,150,154,157],{"class":124,"line":125},[122,147,149],{"class":148},"sag7P","import",[122,151,153],{"class":152},"sqSWz"," { Pyas } ",[122,155,156],{"class":148},"from",[122,158,160],{"class":159},"sk1Au"," '@pyas\u002Fsdk'\n",[122,162,164],{"class":124,"line":163},2,[122,165,167],{"emptyLinePlaceholder":166},true,"\n",[122,169,171,174,178,181,184,187,190,193,196,199,202,204,207],{"class":124,"line":170},3,[122,172,173],{"class":148},"const",[122,175,177],{"class":176},"sXULy"," pyas",[122,179,180],{"class":148}," =",[122,182,183],{"class":148}," new",[122,185,186],{"class":128}," Pyas",[122,188,189],{"class":152},"({ apiKey",[122,191,192],{"class":148},":",[122,194,195],{"class":176}," process",[122,197,198],{"class":152},".",[122,200,201],{"class":176},"env",[122,203,198],{"class":152},[122,205,206],{"class":176},"PYAS_API_KEY",[122,208,209],{"class":152}," })\n",[122,211,213,215,218,220,223,225,227,230,233,236,240],{"class":124,"line":212},4,[122,214,173],{"class":148},[122,216,217],{"class":176}," event",[122,219,180],{"class":148},[122,221,222],{"class":148}," await",[122,224,177],{"class":176},[122,226,198],{"class":128},[122,228,229],{"class":176},"events",[122,231,232],{"class":128},".get",[122,234,235],{"class":152},"({ accountId",[122,237,239],{"class":238},"sEEt9",",",[122,241,242],{"class":152}," eventId })\n",[87,244,245,246,249,250,253,254,257,258,261,262,265],{},"Every operation in the ",[91,247,4],{"href":248},"\u002Freference"," has a method with a matching name, such as ",[108,251,252],{},"pyas.events.list",", ",[108,255,256],{},"pyas.calendars.permissions.create"," and ",[108,259,260],{},"pyas.webhooks.deliveries.replay",". Each method accepts a single object that contains the operation's path, query and body parameters. The exception is ",[108,263,264],{},"events.attachments.upload",", which takes the file as its second argument. The SDK also does the following:",[267,268,269,285,296,306],"ul",{},[270,271,272,273,276,277,280,281,198],"li",{},"Retries rate-limited requests and network failures when it's safe to do so, and honors the ",[108,274,275],{},"Retry-After"," header. It sends an ",[108,278,279],{},"Idempotency-Key"," with every request that creates, changes or deletes something. See ",[91,282,284],{"href":283},"\u002Fidempotency","Retries and idempotency",[270,286,287,288,291,292,295],{},"Iterates through every page when you use ",[108,289,290],{},"for await",", or returns a single page when you ",[108,293,294],{},"await"," the method.",[270,297,298,299,257,302,305],{},"Throws typed errors (such as ",[108,300,301],{},"NotFoundError",[108,303,304],{},"RateLimitError",") that include the API's error code, hint, documentation link and trace id.",[270,307,308,309,198],{},"Verifies webhook signatures with ",[108,310,311],{},"verifyWebhook",[102,313,58],{"id":57},[87,315,316,317,320,321,324,325,328,329,332],{},"You can use the ",[108,318,319],{},"pyas"," CLI in your terminal, or let your coding agent use it. Every command accepts ",[108,322,323],{},"--json",". The CLI exits with code ",[108,326,327],{},"2"," when the command itself is invalid, and with code ",[108,330,331],{},"1"," when the API rejects the request.",[113,334,336],{"className":115,"code":335,"language":117,"meta":118,"style":118},"npx @pyas\u002Fcli login                                  # signs you in through the dashboard, to set up your apps\nnpx @pyas\u002Fcli apps show \u003CappId>                      # the app's setup checklist and the next step\nnpx @pyas\u002Fcli keys test \u003CappId>                      # a test key, printed once\nnpx @pyas\u002Fcli login --key pyas_sk_test_...           # saves a key for the calendar commands\nnpx @pyas\u002Fcli accounts list\nnpx @pyas\u002Fcli events create --account \u003Cid> --title \"Intro call\" --start 2026-10-21T15:00:00Z --duration 30\nnpx @pyas\u002Fcli errors explain CONNECTION_NOT_FOUND\nnpx @pyas\u002Fcli logs get trc_...                      # what a request did, and why it failed\nnpx @pyas\u002Fcli webhooks listen --forward http:\u002F\u002Flocalhost:3000\u002Fwebhooks\n",[108,337,338,353,380,403,420,433,476,492,511],{"__ignoreMap":118},[122,339,340,343,346,349],{"class":124,"line":125},[122,341,342],{"class":128},"npx",[122,344,345],{"class":132}," @pyas\u002Fcli",[122,347,348],{"class":132}," login",[122,350,352],{"class":351},"ssgCD","                                  # signs you in through the dashboard, to set up your apps\n",[122,354,355,357,359,362,365,368,371,374,377],{"class":124,"line":163},[122,356,342],{"class":128},[122,358,345],{"class":132},[122,360,361],{"class":132}," apps",[122,363,364],{"class":132}," show",[122,366,367],{"class":148}," \u003C",[122,369,370],{"class":132},"appI",[122,372,373],{"class":152},"d",[122,375,376],{"class":148},">",[122,378,379],{"class":351},"                      # the app's setup checklist and the next step\n",[122,381,382,384,386,389,392,394,396,398,400],{"class":124,"line":170},[122,383,342],{"class":128},[122,385,345],{"class":132},[122,387,388],{"class":132}," keys",[122,390,391],{"class":132}," test",[122,393,367],{"class":148},[122,395,370],{"class":132},[122,397,373],{"class":152},[122,399,376],{"class":148},[122,401,402],{"class":351},"                      # a test key, printed once\n",[122,404,405,407,409,411,414,417],{"class":124,"line":212},[122,406,342],{"class":128},[122,408,345],{"class":132},[122,410,348],{"class":132},[122,412,413],{"class":132}," --key",[122,415,416],{"class":132}," pyas_sk_test_...",[122,418,419],{"class":351},"           # saves a key for the calendar commands\n",[122,421,423,425,427,430],{"class":124,"line":422},5,[122,424,342],{"class":128},[122,426,345],{"class":132},[122,428,429],{"class":132}," accounts",[122,431,432],{"class":132}," list\n",[122,434,436,438,440,443,446,449,451,454,456,458,461,464,467,470,473],{"class":124,"line":435},6,[122,437,342],{"class":128},[122,439,345],{"class":132},[122,441,442],{"class":132}," events",[122,444,445],{"class":132}," create",[122,447,448],{"class":132}," --account",[122,450,367],{"class":148},[122,452,453],{"class":132},"i",[122,455,373],{"class":152},[122,457,376],{"class":148},[122,459,460],{"class":132}," --title",[122,462,463],{"class":159}," \"Intro call\"",[122,465,466],{"class":132}," --start",[122,468,469],{"class":132}," 2026-10-21T15:00:00Z",[122,471,472],{"class":132}," --duration",[122,474,475],{"class":176}," 30\n",[122,477,479,481,483,486,489],{"class":124,"line":478},7,[122,480,342],{"class":128},[122,482,345],{"class":132},[122,484,485],{"class":132}," errors",[122,487,488],{"class":132}," explain",[122,490,491],{"class":132}," CONNECTION_NOT_FOUND\n",[122,493,495,497,499,502,505,508],{"class":124,"line":494},8,[122,496,342],{"class":128},[122,498,345],{"class":132},[122,500,501],{"class":132}," logs",[122,503,504],{"class":132}," get",[122,506,507],{"class":132}," trc_...",[122,509,510],{"class":351},"                      # what a request did, and why it failed\n",[122,512,514,516,518,521,524,527],{"class":124,"line":513},9,[122,515,342],{"class":128},[122,517,345],{"class":132},[122,519,520],{"class":132}," webhooks",[122,522,523],{"class":132}," listen",[122,525,526],{"class":132}," --forward",[122,528,529],{"class":132}," http:\u002F\u002Flocalhost:3000\u002Fwebhooks\n",[87,531,532,535,536,539,540,544,545,548,549,198],{},[108,533,534],{},"pyas login"," shows a code in your terminal and opens the dashboard, where you enter the code and approve. Only approve a code from a terminal you're using. The sign-in lasts until you run ",[108,537,538],{},"pyas logout"," or disconnect it under ",[541,542,543],"strong",{},"Connected tools"," on your dashboard profile. A coding agent that can't wait for a command to finish can run ",[108,546,547],{},"pyas login --no-wait --json",", show you the code, then run ",[108,550,551],{},"pyas login --wait",[87,553,554,555,558],{},"To call any operation in the reference, use ",[108,556,557],{},"pyas request"," with the operation's id:",[113,560,562],{"className":115,"code":561,"language":117,"meta":118,"style":118},"npx @pyas\u002Fcli request \u003CoperationId> --params '{...}'\n",[108,563,564],{"__ignoreMap":118},[122,565,566,568,570,573,575,578,580,582,585],{"class":124,"line":125},[122,567,342],{"class":128},[122,569,345],{"class":132},[122,571,572],{"class":132}," request",[122,574,367],{"class":148},[122,576,577],{"class":132},"operationI",[122,579,373],{"class":152},[122,581,376],{"class":148},[122,583,584],{"class":132}," --params",[122,586,587],{"class":159}," '{...}'\n",[102,589,61],{"id":60},[87,591,592,593,596,597,599],{},"The ",[541,594,595],{},"Pyas API v2"," collection has every endpoint, each with the example from the ",[91,598,4],{"href":248},". The examples use your sandbox's sample people and events, so they work as soon as you add your key.",[601,602,603,615,626],"ol",{},[270,604,605,606,611,612,614],{},"Open Pyas's public Postman workspace, ",[91,607,610],{"href":608,"rel":609},"https:\u002F\u002Fwww.postman.com\u002Fbrutforce-tech\u002Fpyas-api",[95],"brutforce-tech\u002Fpyas-api",", and fork ",[541,613,595],{}," into your own workspace.",[270,616,617,618,621,622,625],{},"In the collection's ",[541,619,620],{},"Variables"," tab, set ",[108,623,624],{},"apiKey"," to your test key.",[270,627,628],{},"Send any request.",[87,630,592,631,634],{},[541,632,633],{},"Scenarios"," folder runs common tasks step by step, such as finding a time when everyone is free and booking it. Run it with the Collection Runner, and each step passes what the next one needs.",[102,636,64],{"id":63},[87,638,639,640,644],{},"To add Pyas to Claude, Cursor, VS Code or another AI tool by its address, with sign-in and nothing to install, see ",[91,641,643],{"href":642},"\u002Fai-tools","AI tools",". The rest of this section runs the server on your own computer, with an API key.",[87,646,647,650],{},[108,648,649],{},"@pyas\u002Fmcp"," provides calendar tools for AI agents, such as tools to find a time, book it and move it. It also provides coding agents with access to the API reference, the error codes and your request logs. With a test key, the server works only in your sandbox.",[113,652,654],{"className":115,"code":653,"language":117,"meta":118,"style":118},"claude mcp add pyas --env PYAS_API_KEY=pyas_sk_test_... -- npx -y @pyas\u002Fmcp\n",[108,655,656],{"__ignoreMap":118},[122,657,658,661,664,667,669,672,675,678,681,684],{"class":124,"line":125},[122,659,660],{"class":128},"claude",[122,662,663],{"class":132}," mcp",[122,665,666],{"class":132}," add",[122,668,177],{"class":132},[122,670,671],{"class":132}," --env",[122,673,674],{"class":132}," PYAS_API_KEY=pyas_sk_test_...",[122,676,677],{"class":132}," --",[122,679,680],{"class":132}," npx",[122,682,683],{"class":132}," -y",[122,685,686],{"class":132}," @pyas\u002Fmcp\n",[87,688,689],{},"For Claude Desktop, Cursor, Windsurf or VS Code, add the server to the app's MCP settings:",[113,691,695],{"className":692,"code":693,"language":694,"meta":118,"style":118},"language-json shiki shiki-themes css-variables","{\n  \"mcpServers\": {\n    \"pyas\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@pyas\u002Fmcp\"],\n      \"env\": { \"PYAS_API_KEY\": \"pyas_sk_test_...\" }\n    }\n  }\n}\n","json",[108,696,697,702,712,721,734,757,778,783,788],{"__ignoreMap":118},[122,698,699],{"class":124,"line":125},[122,700,701],{"class":152},"{\n",[122,703,704,707,709],{"class":124,"line":163},[122,705,706],{"class":148},"  \"mcpServers\"",[122,708,192],{"class":238},[122,710,711],{"class":152}," {\n",[122,713,714,717,719],{"class":124,"line":170},[122,715,716],{"class":148},"    \"pyas\"",[122,718,192],{"class":238},[122,720,711],{"class":152},[122,722,723,726,728,731],{"class":124,"line":212},[122,724,725],{"class":148},"      \"command\"",[122,727,192],{"class":238},[122,729,730],{"class":159}," \"npx\"",[122,732,733],{"class":238},",\n",[122,735,736,739,741,744,747,749,752,755],{"class":124,"line":422},[122,737,738],{"class":148},"      \"args\"",[122,740,192],{"class":238},[122,742,743],{"class":152}," [",[122,745,746],{"class":159},"\"-y\"",[122,748,239],{"class":238},[122,750,751],{"class":159}," \"@pyas\u002Fmcp\"",[122,753,754],{"class":152},"]",[122,756,733],{"class":238},[122,758,759,762,764,767,770,772,775],{"class":124,"line":435},[122,760,761],{"class":148},"      \"env\"",[122,763,192],{"class":238},[122,765,766],{"class":152}," { ",[122,768,769],{"class":148},"\"PYAS_API_KEY\"",[122,771,192],{"class":238},[122,773,774],{"class":159}," \"pyas_sk_test_...\"",[122,776,777],{"class":152}," }\n",[122,779,780],{"class":124,"line":478},[122,781,782],{"class":152},"    }\n",[122,784,785],{"class":124,"line":494},[122,786,787],{"class":152},"  }\n",[122,789,790],{"class":124,"line":513},[122,791,792],{"class":152},"}\n",[87,794,795,796,799],{},"To provide only the tools that read data, add ",[108,797,798],{},"--read-only"," to the arguments.",[102,801,67],{"id":66},[87,803,804,807,808,198],{},[108,805,806],{},"@pyas\u002Fai-tools"," gives the AI assistant in your own app calendar tools, for the Vercel AI SDK, OpenAI, the Claude API and LangChain. Each person's assistant has access to their calendars only, and asks them before it changes anything. See ",[91,809,811],{"href":810},"\u002Fai-in-your-app","AI in your app",[113,813,815],{"className":115,"code":814,"language":117,"meta":118,"style":118},"npm install @pyas\u002Fai-tools\n",[108,816,817],{"__ignoreMap":118},[122,818,819,821,823],{"class":124,"line":125},[122,820,129],{"class":128},[122,822,133],{"class":132},[122,824,825],{"class":132}," @pyas\u002Fai-tools\n",[102,827,70],{"id":69},[87,829,830,831,834,835,839,840,253,847,253,854,257,861,198],{},"PyasConnect is a sign-in dialog for your page. Your users choose a provider and sign in, and the account is saved. Your server needs a single endpoint, which is one line of code with the SDK: ",[108,832,833],{},"pyas.connect.sessionHandler()",". See ",[91,836,838],{"href":837},"\u002Fconnect","Connecting accounts"," for the setup. Every option is documented on npm: ",[91,841,844],{"href":842,"rel":843},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@pyas\u002Fconnect-react",[95],[108,845,846],{},"@pyas\u002Fconnect-react",[91,848,851],{"href":849,"rel":850},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@pyas\u002Fconnect-vue",[95],[108,852,853],{},"@pyas\u002Fconnect-vue",[91,855,858],{"href":856,"rel":857},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@pyas\u002Fconnect-angular",[95],[108,859,860],{},"@pyas\u002Fconnect-angular",[91,862,865],{"href":863,"rel":864},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@pyas\u002Fconnect",[95],[108,866,867],{},"@pyas\u002Fconnect",[113,869,871],{"className":115,"code":870,"language":117,"meta":118,"style":118},"npm install @pyas\u002Fconnect-react   # or @pyas\u002Fconnect-vue, @pyas\u002Fconnect-angular, @pyas\u002Fconnect\n",[108,872,873],{"__ignoreMap":118},[122,874,875,877,879,882],{"class":124,"line":125},[122,876,129],{"class":128},[122,878,133],{"class":132},[122,880,881],{"class":132}," @pyas\u002Fconnect-react",[122,883,884],{"class":351},"   # or @pyas\u002Fconnect-vue, @pyas\u002Fconnect-angular, @pyas\u002Fconnect\n",[102,886,73],{"id":72},[267,888,889,905,913],{},[270,890,891,897,898,904],{},[91,892,894],{"href":893},"\u002Fllms.txt",[108,895,896],{},"llms.txt"," lists every page of these docs, and ",[91,899,901],{"href":900},"\u002Fllms-full.txt",[108,902,903],{},"llms-full.txt"," contains all of them in a single file.",[270,906,592,907,912],{},[91,908,911],{"href":909,"rel":910},"https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Ferrors",[95],"error codes endpoint"," returns every error code with its cause and fix, as structured data.",[270,914,915,916,919,920,923,924],{},"Every error response includes a ",[108,917,918],{},"traceId",". To see what the request did and why it failed, run ",[108,921,922],{},"pyas logs get"," or call:",[113,925,929],{"className":926,"code":927,"language":928,"meta":118,"style":118},"language-http shiki shiki-themes css-variables","GET \u002Fv2\u002Flogs\u002F{traceId}\n","http",[108,930,931],{"__ignoreMap":118},[122,932,933,936],{"class":124,"line":125},[122,934,935],{"class":148},"GET",[122,937,938],{"class":152}," \u002Fv2\u002Flogs\u002F{traceId}\n",[940,941,942],"style",{},"html pre.shiki code .s1IGz, html code.shiki .s1IGz{--shiki-default:var(--shiki-token-function)}html pre.shiki code .sTB4W, html code.shiki .sTB4W{--shiki-default:var(--shiki-token-string)}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sag7P, html code.shiki .sag7P{--shiki-default:var(--shiki-token-keyword)}html pre.shiki code .sqSWz, html code.shiki .sqSWz{--shiki-default:var(--shiki-foreground)}html pre.shiki code .sk1Au, html code.shiki .sk1Au{--shiki-default:var(--shiki-token-string-expression)}html pre.shiki code .sXULy, html code.shiki .sXULy{--shiki-default:var(--shiki-token-constant)}html pre.shiki code .sEEt9, html code.shiki .sEEt9{--shiki-default:var(--shiki-token-punctuation)}html pre.shiki code .ssgCD, html code.shiki .ssgCD{--shiki-default:var(--shiki-token-comment)}",{"title":118,"searchDepth":170,"depth":170,"links":944},[945,946,947,948,949,950,951],{"id":54,"depth":163,"text":55},{"id":57,"depth":163,"text":58},{"id":60,"depth":163,"text":61},{"id":63,"depth":163,"text":64},{"id":66,"depth":163,"text":67},{"id":69,"depth":163,"text":70},{"id":72,"depth":163,"text":73},"md",false,{},"\u002Fsdks","---\ntitle: SDKs and tools\ndescription: The Node.js SDK, the CLI, the Postman collection, the MCP server and AI tools, and PyasConnect for your frontend.\nsections:\n  - { id: official-libraries, title: Official libraries }\n  - { id: nodejs-and-typescript, title: Node.js and TypeScript }\n  - { id: the-cli, title: The CLI }\n  - { id: postman, title: Postman }\n  - { id: mcp-server, title: MCP server }\n  - { id: ai-tools-for-your-app, title: AI tools for your app }\n  - { id: pyasconnect, title: PyasConnect }\n  - { id: for-coding-agents, title: For coding agents }\n---\n\n# SDKs and tools\n\n::lead\nThe Pyas API uses plain HTTPS and JSON, and an [OpenAPI document](https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fopenapi.json) describes every endpoint. The tools on this page make common tasks quicker for you and for your coding agent.\n::\n\n::libraries\n::\n\n## Node.js and TypeScript\n\nThe types in `@pyas\u002Fsdk` are generated from the OpenAPI document, so your editor can autocomplete every field. The SDK requires Node 20 or later and has no dependencies.\n\n```bash\nnpm install @pyas\u002Fsdk\n```\n\n```js\nimport { Pyas } from '@pyas\u002Fsdk'\n\nconst pyas = new Pyas({ apiKey: process.env.PYAS_API_KEY })\nconst event = await pyas.events.get({ accountId, eventId })\n```\n\nEvery operation in the [API reference](\u002Freference) has a method with a matching name, such as `pyas.events.list`, `pyas.calendars.permissions.create` and `pyas.webhooks.deliveries.replay`. Each method accepts a single object that contains the operation's path, query and body parameters. The exception is `events.attachments.upload`, which takes the file as its second argument. The SDK also does the following:\n\n- Retries rate-limited requests and network failures when it's safe to do so, and honors the `Retry-After` header. It sends an `Idempotency-Key` with every request that creates, changes or deletes something. See [Retries and idempotency](\u002Fidempotency).\n- Iterates through every page when you use `for await`, or returns a single page when you `await` the method.\n- Throws typed errors (such as `NotFoundError` and `RateLimitError`) that include the API's error code, hint, documentation link and trace id.\n- Verifies webhook signatures with `verifyWebhook`.\n\n## The CLI\n\nYou can use the `pyas` CLI in your terminal, or let your coding agent use it. Every command accepts `--json`. The CLI exits with code `2` when the command itself is invalid, and with code `1` when the API rejects the request.\n\n```bash\nnpx @pyas\u002Fcli login                                  # signs you in through the dashboard, to set up your apps\nnpx @pyas\u002Fcli apps show \u003CappId>                      # the app's setup checklist and the next step\nnpx @pyas\u002Fcli keys test \u003CappId>                      # a test key, printed once\nnpx @pyas\u002Fcli login --key pyas_sk_test_...           # saves a key for the calendar commands\nnpx @pyas\u002Fcli accounts list\nnpx @pyas\u002Fcli events create --account \u003Cid> --title \"Intro call\" --start 2026-10-21T15:00:00Z --duration 30\nnpx @pyas\u002Fcli errors explain CONNECTION_NOT_FOUND\nnpx @pyas\u002Fcli logs get trc_...                      # what a request did, and why it failed\nnpx @pyas\u002Fcli webhooks listen --forward http:\u002F\u002Flocalhost:3000\u002Fwebhooks\n```\n\n`pyas login` shows a code in your terminal and opens the dashboard, where you enter the code and approve. Only approve a code from a terminal you're using. The sign-in lasts until you run `pyas logout` or disconnect it under **Connected tools** on your dashboard profile. A coding agent that can't wait for a command to finish can run `pyas login --no-wait --json`, show you the code, then run `pyas login --wait`.\n\nTo call any operation in the reference, use `pyas request` with the operation's id:\n\n```bash\nnpx @pyas\u002Fcli request \u003CoperationId> --params '{...}'\n```\n\n## Postman\n\nThe **Pyas API v2** collection has every endpoint, each with the example from the [API reference](\u002Freference). The examples use your sandbox's sample people and events, so they work as soon as you add your key.\n\n1. Open Pyas's public Postman workspace, [brutforce-tech\u002Fpyas-api](https:\u002F\u002Fwww.postman.com\u002Fbrutforce-tech\u002Fpyas-api), and fork **Pyas API v2** into your own workspace.\n2. In the collection's **Variables** tab, set `apiKey` to your test key.\n3. Send any request.\n\nThe **Scenarios** folder runs common tasks step by step, such as finding a time when everyone is free and booking it. Run it with the Collection Runner, and each step passes what the next one needs.\n\n## MCP server\n\nTo add Pyas to Claude, Cursor, VS Code or another AI tool by its address, with sign-in and nothing to install, see [AI tools](\u002Fai-tools). The rest of this section runs the server on your own computer, with an API key.\n\n`@pyas\u002Fmcp` provides calendar tools for AI agents, such as tools to find a time, book it and move it. It also provides coding agents with access to the API reference, the error codes and your request logs. With a test key, the server works only in your sandbox.\n\n```bash\nclaude mcp add pyas --env PYAS_API_KEY=pyas_sk_test_... -- npx -y @pyas\u002Fmcp\n```\n\nFor Claude Desktop, Cursor, Windsurf or VS Code, add the server to the app's MCP settings:\n\n```json\n{\n  \"mcpServers\": {\n    \"pyas\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@pyas\u002Fmcp\"],\n      \"env\": { \"PYAS_API_KEY\": \"pyas_sk_test_...\" }\n    }\n  }\n}\n```\n\nTo provide only the tools that read data, add `--read-only` to the arguments.\n\n## AI tools for your app\n\n`@pyas\u002Fai-tools` gives the AI assistant in your own app calendar tools, for the Vercel AI SDK, OpenAI, the Claude API and LangChain. Each person's assistant has access to their calendars only, and asks them before it changes anything. See [AI in your app](\u002Fai-in-your-app).\n\n```bash\nnpm install @pyas\u002Fai-tools\n```\n\n## PyasConnect\n\nPyasConnect is a sign-in dialog for your page. Your users choose a provider and sign in, and the account is saved. Your server needs a single endpoint, which is one line of code with the SDK: `pyas.connect.sessionHandler()`. See [Connecting accounts](\u002Fconnect) for the setup. Every option is documented on npm: [`@pyas\u002Fconnect-react`](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@pyas\u002Fconnect-react), [`@pyas\u002Fconnect-vue`](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@pyas\u002Fconnect-vue), [`@pyas\u002Fconnect-angular`](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@pyas\u002Fconnect-angular) and [`@pyas\u002Fconnect`](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@pyas\u002Fconnect).\n\n```bash\nnpm install @pyas\u002Fconnect-react   # or @pyas\u002Fconnect-vue, @pyas\u002Fconnect-angular, @pyas\u002Fconnect\n```\n\n## For coding agents\n\n- [`llms.txt`](\u002Fllms.txt) lists every page of these docs, and [`llms-full.txt`](\u002Fllms-full.txt) contains all of them in a single file.\n- The [error codes endpoint](https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Ferrors) returns every error code with its cause and fix, as structured data.\n- Every error response includes a `traceId`. To see what the request did and why it failed, run `pyas logs get` or call:\n\n  ```http\n  GET \u002Fv2\u002Flogs\u002F{traceId}\n  ```\n",{"title":47,"description":48},"sdks",null,"Btd5cWeSfgUeXxlfLz1vO_2U-4mNluBDx8jTuca191k",1794697270626]