[{"data":1,"prerenderedAt":540},["ShallowReactive",2],{"navigation":3,"page:\u002Fsandbox":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":65},"guide","The sandbox","Sample people with a week of events, simulated Google, Outlook and Zoom accounts, and changes, meetings and failures that you trigger on demand.",[50,53,56,59,62],{"id":51,"title":52},"whats-in-the-sandbox","What's in the sandbox",{"id":54,"title":55},"reset-the-sandbox","Reset the sandbox",{"id":57,"title":58},"simulate-changes","Simulate changes",{"id":60,"title":61},"simulate-provider-errors","Simulate provider errors",{"id":63,"title":64},"limits","Limits",{"id":66,"title":47,"body":67,"description":48,"extension":530,"hero":531,"meta":532,"navigation":533,"path":534,"rawbody":535,"sections":536,"seo":537,"stem":538,"v1":536,"__hash__":539},"docs\u002Fsandbox.md",{"type":68,"value":69,"toc":523},"minimark",[70,74,81,84,87,110,200,203,206,219,235,237,240,252,263,265,273,317,386,397,399,410,505,508,510,516,519],[71,72,47],"h1",{"id":73},"the-sandbox",[75,76,77],"lead",{},[78,79,80],"p",{},"Every app has a sandbox that you access with the app's test keys. The sandbox is ready on your first request and doesn't connect to any real calendar. It returns the same responses and errors as the live API.",[82,83,52],"h2",{"id":51},[78,85,86],{},"The sandbox starts with the people below. Each of them has a Pyas calendar with a week of events, including stand-ups, one-on-ones, a design review, focus time and an offsite. To add your own people, create accounts with:",[88,89,94],"pre",{"className":90,"code":91,"language":92,"meta":93,"style":93},"language-http shiki shiki-themes css-variables","POST \u002Fv2\u002Faccounts\n","http","",[95,96,97],"code",{"__ignoreMap":93},[98,99,102,106],"span",{"class":100,"line":101},"line",1,[98,103,105],{"class":104},"sag7P","POST",[98,107,109],{"class":108},"sqSWz"," \u002Fv2\u002Faccounts\n",[111,112,113,131],"table",{},[114,115,116],"thead",{},[117,118,119,123,126],"tr",{},[120,121,122],"th",{},"Person",[120,124,125],{},"Time zone",[120,127,128],{},[95,129,130],{},"subjectId",[132,133,134,148,161,174,187],"tbody",{},[117,135,136,140,143],{},[137,138,139],"td",{},"Avery Brooks",[137,141,142],{},"America\u002FNew_York",[137,144,145],{},[95,146,147],{},"sandbox_user_1",[117,149,150,153,156],{},[137,151,152],{},"Sam Patel",[137,154,155],{},"Europe\u002FLondon",[137,157,158],{},[95,159,160],{},"sandbox_user_2",[117,162,163,166,169],{},[137,164,165],{},"Yuki Tanaka",[137,167,168],{},"Asia\u002FTokyo",[137,170,171],{},[95,172,173],{},"sandbox_user_3",[117,175,176,179,182],{},[137,177,178],{},"Jordan Lee",[137,180,181],{},"America\u002FLos_Angeles",[137,183,184],{},[95,185,186],{},"sandbox_user_4",[117,188,189,192,195],{},[137,190,191],{},"Riley Chen",[137,193,194],{},"UTC",[137,196,197],{},[95,198,199],{},"sandbox_user_5",[78,201,202],{},"The sandbox also includes simulated provider accounts. Avery has a Google account and a Zoom account, and Sam has an Outlook account. These accounts behave like real Google, Outlook and Zoom accounts, with the same features and the same errors, but the API never contacts the providers for them. The following all behave as they would on a real account: Meet and Teams links, Zoom meetings, sharing roles, Outlook categories, calendar groups, invitations to respond to, attachments, reminders and working locations.",[78,204,205],{},"To get the ids of the accounts, calendars and events in your sandbox, call:",[88,207,209],{"className":90,"code":208,"language":92,"meta":93,"style":93},"GET \u002Fv2\u002Fsandbox\n",[95,210,211],{"__ignoreMap":93},[98,212,213,216],{"class":100,"line":101},[98,214,215],{"class":104},"GET",[98,217,218],{"class":108}," \u002Fv2\u002Fsandbox\n",[78,220,221,222,225,226,229,230,234],{},"The response lists each id under the same name that the reference examples use, such as ",[95,223,224],{},"account.avery"," and ",[95,227,228],{},"event.avery.design",". The ",[231,232,4],"a",{"href":233},"\u002Freference"," shows the ids from a sample sandbox. Your sandbox has the same people and events, but with its own ids.",[82,236,55],{"id":54},[78,238,239],{},"To restore the sandbox to the state it was in on your first request, call:",[88,241,243],{"className":90,"code":242,"language":92,"meta":93,"style":93},"POST \u002Fv2\u002Fsandbox\u002Freset\n",[95,244,245],{"__ignoreMap":93},[98,246,247,249],{"class":100,"line":101},[98,248,105],{"class":104},[98,250,251],{"class":108}," \u002Fv2\u002Fsandbox\u002Freset\n",[78,253,254,255,258,259,262],{},"You can reset the sandbox between test runs. You can also reset it from the dashboard. In Test mode, go to ",[256,257,7],"strong",{}," and select ",[256,260,261],{},"Reset sandbox",".",[82,264,58],{"id":57},[78,266,267,268,272],{},"On a live account, events change when people update their calendars, reply to invitations or join meetings. In the sandbox, you trigger these changes yourself with the endpoints below. The sandbox then sends the same ",[231,269,271],{"href":270},"\u002Fwebhooks","webhooks"," that a live account sends.",[111,274,275,285],{},[114,276,277],{},[117,278,279,282],{},[120,280,281],{},"Endpoint",[120,283,284],{},"What it simulates",[132,286,287,297,307],{},[117,288,289,294],{},[137,290,291],{},[95,292,293],{},"POST \u002Fv2\u002Fsandbox\u002Fsimulate-change",[137,295,296],{},"An event is created, updated or deleted on the account, as if the person did it in their own calendar app",[117,298,299,304],{},[137,300,301],{},[95,302,303],{},"POST \u002Fv2\u002Fsandbox\u002Fsimulate-meeting",[137,305,306],{},"A meeting starts or ends, someone joins or leaves, or a recording becomes available",[117,308,309,314],{},[137,310,311],{},[95,312,313],{},"POST \u002Fv2\u002Fsandbox\u002Fsimulate-reply",[137,315,316],{},"An attendee accepts, declines or responds with maybe, and can propose a different time",[88,318,322],{"className":319,"code":320,"language":321,"meta":93,"style":93},"language-bash shiki shiki-themes css-variables","curl -X POST https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fsandbox\u002Fsimulate-reply \\\n  -H \"x-api-key: $PYAS_API_KEY\" \\\n  -H \"content-type: application\u002Fjson\" \\\n  -d '{ \"accountId\": \"'$ACCOUNT_ID'\", \"eventId\": \"'$EVENT_ID'\", \"email\": \"sam.patel@example.org\", \"response\": \"declined\" }'\n","bash",[95,323,324,343,355,365],{"__ignoreMap":93},[98,325,326,330,334,337,340],{"class":100,"line":101},[98,327,329],{"class":328},"s1IGz","curl",[98,331,333],{"class":332},"sTB4W"," -X",[98,335,336],{"class":332}," POST",[98,338,339],{"class":332}," https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fsandbox\u002Fsimulate-reply",[98,341,342],{"class":108}," \\\n",[98,344,346,349,353],{"class":100,"line":345},2,[98,347,348],{"class":332},"  -H",[98,350,352],{"class":351},"sk1Au"," \"x-api-key: $PYAS_API_KEY\"",[98,354,342],{"class":108},[98,356,358,360,363],{"class":100,"line":357},3,[98,359,348],{"class":332},[98,361,362],{"class":351}," \"content-type: application\u002Fjson\"",[98,364,342],{"class":108},[98,366,368,371,374,377,380,383],{"class":100,"line":367},4,[98,369,370],{"class":332},"  -d",[98,372,373],{"class":351}," '{ \"accountId\": \"'",[98,375,376],{"class":108},"$ACCOUNT_ID",[98,378,379],{"class":351},"'\", \"eventId\": \"'",[98,381,382],{"class":108},"$EVENT_ID",[98,384,385],{"class":351},"'\", \"email\": \"sam.patel@example.org\", \"response\": \"declined\" }'\n",[78,387,388,389,392,393,262],{},"For a reply, the event must be on one of the sample people's Pyas calendars, not on the simulated Google, Outlook or Zoom account, and ",[95,390,391],{},"email"," must be one of its attendees. This example replies for the attendee invited in the ",[231,394,396],{"href":395},"\u002Fquickstart","Quickstart",[82,398,61],{"id":60},[78,400,401,402,405,406,409],{},"To test how your app handles provider failures, add ",[95,403,404],{},"?simulate="," (or a ",[95,407,408],{},"Pyas-Simulate"," header) to any request made with a test key. The request then fails in the same way it would if a real provider failed:",[111,411,412,422],{},[114,413,414],{},[117,415,416,419],{},[120,417,418],{},"Value",[120,420,421],{},"Response",[132,423,424,443,459,475,490],{},[117,425,426,431],{},[137,427,428],{},[95,429,430],{},"rate_limit",[137,432,433,439,440],{},[231,434,436],{"href":435},"\u002Ferrors\u002FPROVIDER_RATE_LIMITED",[95,437,438],{},"PROVIDER_RATE_LIMITED",", with ",[95,441,442],{},"Retry-After",[117,444,445,450],{},[137,446,447],{},[95,448,449],{},"token_expired",[137,451,452,458],{},[231,453,455],{"href":454},"\u002Ferrors\u002FCONNECTION_TOKEN_EXPIRED",[95,456,457],{},"CONNECTION_TOKEN_EXPIRED",". The user needs to sign in again.",[117,460,461,466],{},[137,462,463],{},[95,464,465],{},"revoked",[137,467,468,474],{},[231,469,471],{"href":470},"\u002Ferrors\u002FCONNECTION_REVOKED",[95,472,473],{},"CONNECTION_REVOKED",". The user revoked your access.",[117,476,477,482],{},[137,478,479],{},[95,480,481],{},"provider_error",[137,483,484],{},[231,485,487],{"href":486},"\u002Ferrors\u002FPROVIDER_UNAVAILABLE",[95,488,489],{},"PROVIDER_UNAVAILABLE",[117,491,492,497],{},[137,493,494],{},[95,495,496],{},"timeout",[137,498,499],{},[231,500,502],{"href":501},"\u002Ferrors\u002FPROVIDER_TIMEOUT",[95,503,504],{},"PROVIDER_TIMEOUT",[78,506,507],{},"Your error handling code receives the same error codes, hints and HTTP status codes that it receives in production.",[82,509,64],{"id":63},[78,511,512,513,262],{},"A sandbox can hold up to 25 accounts, 10 calendars per account and 5,000 events. Calendar feeds created in the sandbox work for 7 days. If a sandbox receives no requests for 30 days, it's deleted, and a new one is created on your next request. If you exceed a limit, the API returns ",[95,514,515],{},"RESOURCE_LIMIT_REACHED",[78,517,518],{},"Requests made with a test key don't count toward your plan's monthly request allowance. They have a separate monthly allowance that's large enough for test suites and CI.",[520,521,522],"style",{},"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 .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 .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 pre.shiki code .sk1Au, html code.shiki .sk1Au{--shiki-default:var(--shiki-token-string-expression)}",{"title":93,"searchDepth":357,"depth":357,"links":524},[525,526,527,528,529],{"id":51,"depth":345,"text":52},{"id":54,"depth":345,"text":55},{"id":57,"depth":345,"text":58},{"id":60,"depth":345,"text":61},{"id":63,"depth":345,"text":64},"md",false,{},true,"\u002Fsandbox","---\ntitle: The sandbox\ndescription: Sample people with a week of events, simulated Google, Outlook and Zoom accounts, and changes, meetings and failures that you trigger on demand.\n---\n\n# The sandbox\n\n::lead\nEvery app has a sandbox that you access with the app's test keys. The sandbox is ready on your first request and doesn't connect to any real calendar. It returns the same responses and errors as the live API.\n::\n\n## What's in the sandbox\n\nThe sandbox starts with the people below. Each of them has a Pyas calendar with a week of events, including stand-ups, one-on-ones, a design review, focus time and an offsite. To add your own people, create accounts with:\n\n```http\nPOST \u002Fv2\u002Faccounts\n```\n\n| Person | Time zone | `subjectId` |\n|---|---|---|\n| Avery Brooks | America\u002FNew_York | `sandbox_user_1` |\n| Sam Patel | Europe\u002FLondon | `sandbox_user_2` |\n| Yuki Tanaka | Asia\u002FTokyo | `sandbox_user_3` |\n| Jordan Lee | America\u002FLos_Angeles | `sandbox_user_4` |\n| Riley Chen | UTC | `sandbox_user_5` |\n\nThe sandbox also includes simulated provider accounts. Avery has a Google account and a Zoom account, and Sam has an Outlook account. These accounts behave like real Google, Outlook and Zoom accounts, with the same features and the same errors, but the API never contacts the providers for them. The following all behave as they would on a real account: Meet and Teams links, Zoom meetings, sharing roles, Outlook categories, calendar groups, invitations to respond to, attachments, reminders and working locations.\n\nTo get the ids of the accounts, calendars and events in your sandbox, call:\n\n```http\nGET \u002Fv2\u002Fsandbox\n```\n\nThe response lists each id under the same name that the reference examples use, such as `account.avery` and `event.avery.design`. The [API reference](\u002Freference) shows the ids from a sample sandbox. Your sandbox has the same people and events, but with its own ids.\n\n## Reset the sandbox\n\nTo restore the sandbox to the state it was in on your first request, call:\n\n```http\nPOST \u002Fv2\u002Fsandbox\u002Freset\n```\n\nYou can reset the sandbox between test runs. You can also reset it from the dashboard. In Test mode, go to **Accounts** and select **Reset sandbox**.\n\n## Simulate changes\n\nOn a live account, events change when people update their calendars, reply to invitations or join meetings. In the sandbox, you trigger these changes yourself with the endpoints below. The sandbox then sends the same [webhooks](\u002Fwebhooks) that a live account sends.\n\n| Endpoint | What it simulates |\n|---|---|\n| `POST \u002Fv2\u002Fsandbox\u002Fsimulate-change` | An event is created, updated or deleted on the account, as if the person did it in their own calendar app |\n| `POST \u002Fv2\u002Fsandbox\u002Fsimulate-meeting` | A meeting starts or ends, someone joins or leaves, or a recording becomes available |\n| `POST \u002Fv2\u002Fsandbox\u002Fsimulate-reply` | An attendee accepts, declines or responds with maybe, and can propose a different time |\n\n```bash\ncurl -X POST https:\u002F\u002Fapi.pyas.io\u002Fv2\u002Fsandbox\u002Fsimulate-reply \\\n  -H \"x-api-key: $PYAS_API_KEY\" \\\n  -H \"content-type: application\u002Fjson\" \\\n  -d '{ \"accountId\": \"'$ACCOUNT_ID'\", \"eventId\": \"'$EVENT_ID'\", \"email\": \"sam.patel@example.org\", \"response\": \"declined\" }'\n```\n\nFor a reply, the event must be on one of the sample people's Pyas calendars, not on the simulated Google, Outlook or Zoom account, and `email` must be one of its attendees. This example replies for the attendee invited in the [Quickstart](\u002Fquickstart).\n\n## Simulate provider errors\n\nTo test how your app handles provider failures, add `?simulate=` (or a `Pyas-Simulate` header) to any request made with a test key. The request then fails in the same way it would if a real provider failed:\n\n| Value | Response |\n|---|---|\n| `rate_limit` | [`PROVIDER_RATE_LIMITED`](\u002Ferrors\u002FPROVIDER_RATE_LIMITED), with `Retry-After` |\n| `token_expired` | [`CONNECTION_TOKEN_EXPIRED`](\u002Ferrors\u002FCONNECTION_TOKEN_EXPIRED). The user needs to sign in again. |\n| `revoked` | [`CONNECTION_REVOKED`](\u002Ferrors\u002FCONNECTION_REVOKED). The user revoked your access. |\n| `provider_error` | [`PROVIDER_UNAVAILABLE`](\u002Ferrors\u002FPROVIDER_UNAVAILABLE) |\n| `timeout` | [`PROVIDER_TIMEOUT`](\u002Ferrors\u002FPROVIDER_TIMEOUT) |\n\nYour error handling code receives the same error codes, hints and HTTP status codes that it receives in production.\n\n## Limits\n\nA sandbox can hold up to 25 accounts, 10 calendars per account and 5,000 events. Calendar feeds created in the sandbox work for 7 days. If a sandbox receives no requests for 30 days, it's deleted, and a new one is created on your next request. If you exceed a limit, the API returns `RESOURCE_LIMIT_REACHED`.\n\nRequests made with a test key don't count toward your plan's monthly request allowance. They have a separate monthly allowance that's large enough for test suites and CI.\n",null,{"title":47,"description":48},"sandbox","x4E7xOa5ZMaa2UbNXyXp5FieWsHTN59AXll3bVnGuTU",1794697270738]