Using API v1? See what changes in v2, or the v1 docs
Connect
Connect and reconnect calendar accounts with connect sessions, including the steps that run in the user's browser.
The examples use IDs from a sample sandbox. Your sandbox has the same people, calendars and events with its own IDs, which GET /v2/sandbox returns. When you're signed in to the dashboard, Try it fills in your IDs and sends the request to your sandbox, never to live data.
Connect an account with a code
Exchanges the code for tokens, saves the account and returns it. This is the second step of connecting an account from your server without PyasConnect, and it replaces v1's POST /{provider}/connect. Send the code that the provider returned. If the same person connects an account that is already connected, Pyas reconnects it and the account keeps its accountId.
In the sandbox: Send the code that your Redirect URL (Pyas Auth) or your own callback URL (Native Auth) received after GET /v2/connect/oauth. This request requires a live key.
Headers
- Name
Idempotency-Key- Type
- string
- Description
A unique key that makes the request safe to retry. A retry with the same key returns the original response and does not make the change twice. Keys are kept for 24 hours.
Body
- Name
provider- Type
- string
- Required
- required
- Description
The provider in
GET /v2/connect/oauth. One ofgoogle,microsoft,zoom.
- Name
code- Type
- string
- Required
- required
- Description
The
codethat the provider returned to your Redirect URL or callback URL.
- Name
subjectId- Type
- string
- Description
Your own identifier for the user, stored on the account.
- Name
features- Type
- array of string
- Description
The same features as in
GET /v2/connect/oauth. One ofmanageCalendars,sharing,meetingSettings,attachmentUploads,rooms.
- Name
redirectUrl- Type
- string
- Description
The same
redirectUrlas inGET /v2/connect/oauth, if you sent one.
Errors
VALIDATION_INVALID_BODY(400): The request body is not valid.AUTH_INVALID_KEY(401): The API key is missing, unknown or revoked.AUTH_EXPIRED_KEY(401): The API key has expired.BILLING_CONNECTION_LIMIT(402): The plan's connected account limit has been reached.AUTH_SANDBOX_MISMATCH(403): A test key was used with live data, or a live key was used with sandbox data.AUTH_INSUFFICIENT_SCOPE(403): The API key or session does not have permission to make this request.CONNECTION_PROVIDER_NOT_CONFIGURED(422): The app is not configured to connect accounts from this provider.CONNECTION_CONSENT_FAILED(422): The provider did not complete the connection.RATE_LIMIT_EXCEEDED(429): The request rate exceeds this plan's rate limit.RATE_LIMIT_BURST(429): Too many requests were sent in a short period.INTERNAL_ERROR(500): Something went wrong on our end.
Request
curl -X POST 'https://api.pyas.io/v2/connect/accounts' \ -H "x-api-key: $PYAS_API_KEY" \ -H "content-type: application/json" \ -d '{ "provider": "google", "code": "4/0AeanS0Z...", "subjectId": "user_123"}'Response
{ "success": true, "data": { "accountId": "ef66ec55-7f3c-44f8-8e6d-3e8bc2fafc4b", "provider": "google", "email": "avery.brooks@example.com", "name": "Avery Brooks", "subjectId": "user_123", "existing": true, "grantedScopes": null }, "provider": null, "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d", "meta": {}}Get the consent URL (popup mode)
Returns the provider's consent URL to open in a popup. This is the second step. Call it from your page with the session's token, from one of the app's allowed origins. For a session created with a test key, the URL is a Pyas sandbox page instead of the provider's. Requesting a new URL, for example after the user switches provider, invalidates the previous one.
In the sandbox: Call this from your page with a session's token. Create the session on your server with POST /v2/connect/sessions.
PyasConnect sends this request from the browser with a connect session token, so you can't try it with an API key.
Body
- Name
token- Type
- string
- Required
- required
- Description
The session's token.
- Name
provider- Type
- string
- Description
google,microsoftorzoom. Must be one of the session's providers. Optional when the session offers only one provider.
Errors
VALIDATION_INVALID_BODY(400): The request body is not valid.AUTH_INVALID_CONNECT_SESSION(401): The connect session is missing, invalid, expired or already used.AUTH_ORIGIN_NOT_ALLOWED(403): The request's origin is not in the app's allowed origins.CONNECTION_PROVIDER_NOT_CONFIGURED(422): The app is not configured to connect accounts from this provider.INTERNAL_ERROR(500): Something went wrong on our end.
Request
curl -X POST 'https://api.pyas.io/v2/connect/authorize' \ -H "x-api-key: $PYAS_API_KEY" \ -H "content-type: application/json" \ -d '{ "token": "pcs_your-session-token", "provider": "google"}'Response
{ "success": true, "data": { "provider": "google", "url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=1234567890-pyas.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fapi.pyas.io%2Foauth%2Fgoogle%2Fcallback&response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.events+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.freebusy+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.events.freebusy+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.calendarlist.readonly+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.calendars.readonly+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.settings.readonly&access_type=offline&prompt=consent&include_granted_scopes=true&state=app_id%3D5c1e9a47-2d3b-4f86-a0e9-7b4c2d18f365_rest%3Dpcs1.cs_99bec7442c4db29a8539d679.9Z_srW0El4rA9gop9VssvA", "expiresAt": "2026-11-14T20:10:32.621Z" }, "provider": null, "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d", "meta": {}}Complete a connection
Exchanges the code that the provider returned and saves the account. This is the third step. Send the code and state that the provider returned. For a session created with a test key, the code comes from the Pyas sandbox page and the account is a simulated one in your sandbox. Each session can be completed only once.
In the sandbox: Send the code and state that the provider returns after sign-in.
PyasConnect sends this request from the browser with a connect session token, so you can't try it with an API key.
Body
- Name
token- Type
- string
- Required
- required
- Description
The session's token.
- Name
code- Type
- string
- Required
- required
- Description
The
codethat the provider returned.
- Name
state- Type
- string
- Required
- required
- Description
The
statethat the provider returned.
Errors
VALIDATION_INVALID_BODY(400): The request body is not valid.AUTH_INVALID_CONNECT_SESSION(401): The connect session is missing, invalid, expired or already used.BILLING_CONNECTION_LIMIT(402): The plan's connected account limit has been reached.AUTH_ORIGIN_NOT_ALLOWED(403): The request's origin is not in the app's allowed origins.RESOURCE_LIMIT_REACHED(409): The limit for this resource has been reached.CONNECTION_CONSENT_FAILED(422): The provider did not complete the connection.CONNECTION_PROVIDER_NOT_CONFIGURED(422): The app is not configured to connect accounts from this provider.INTERNAL_ERROR(500): Something went wrong on our end.
Request
curl -X POST 'https://api.pyas.io/v2/connect/complete' \ -H "x-api-key: $PYAS_API_KEY" \ -H "content-type: application/json" \ -d '{ "token": "pcs_your-session-token", "code": "the-code-from-the-provider", "state": "the-state-from-the-provider"}'Response
{ "success": true, "data": { "accountId": "ef66ec55-7f3c-44f8-8e6d-3e8bc2fafc4b", "provider": "google", "email": "avery.brooks@example.com", "name": "Avery Brooks", "subjectId": "user_123", "existing": false, "grantedScopes": null }, "provider": null, "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d", "meta": {}}Start a connection (redirect mode)
The url of a redirect-mode session. It redirects the user to the provider's consent page, after showing a provider chooser when the session offers more than one provider. For a session created with a test key, it redirects to a Pyas sandbox page instead. This is a page for browsers, not an API endpoint.
In the sandbox: The url of a redirect-mode session, opened in a browser.
PyasConnect sends this request from the browser with a connect session token, so you can't try it with an API key.
Query parameters
- Name
token- Type
- string
- Required
- required
- Description
The session's token, included in its
url.
- Name
provider- Type
- string
- Description
The provider to use:
google,microsoftorzoom. Sending it skips the provider chooser.
- Name
locale- Type
- string
- Description
The language of the pages:
en,nb,sv,da,de,fr,es,nlorpt-BR. If you leave it out, the browser's language is used, then English.
Errors
INTERNAL_ERROR(500): Something went wrong on our end.
Request
curl 'https://api.pyas.io/v2/connect/go?token=pcs_your-session-token' \ -H "x-api-key: $PYAS_API_KEY"Get connect widget details
Returns the details that the connect widget displays before the user signs in. These include your app's name and icon from the dashboard, the providers the session offers and, for a reconnect, the account to reconnect. Call it from your page with the session's token, from one of the app's allowed origins. This request has no side effects.
In the sandbox: Call this from your page with a session's token, before the user signs in. Create the session on your server with POST /v2/connect/sessions.
PyasConnect sends this request from the browser with a connect session token, so you can't try it with an API key.
Body
- Name
token- Type
- string
- Required
- required
- Description
The session's token.
Errors
VALIDATION_INVALID_BODY(400): The request body is not valid.AUTH_INVALID_CONNECT_SESSION(401): The connect session is missing, invalid, expired or already used.AUTH_ORIGIN_NOT_ALLOWED(403): The request's origin is not in the app's allowed origins.INTERNAL_ERROR(500): Something went wrong on our end.
Request
curl -X POST 'https://api.pyas.io/v2/connect/info' \ -H "x-api-key: $PYAS_API_KEY" \ -H "content-type: application/json" \ -d '{ "token": "pcs_your-session-token"}'Response
{ "success": true, "data": { "app": { "name": "Acme Scheduler", "iconUrl": null }, "providers": [ "google", "microsoft" ], "reconnect": null, "loginHint": null, "expiresAt": "2026-11-14T20:10:32.621Z" }, "provider": null, "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d", "meta": {}}Get a sign-in URL
Returns the provider's sign-in URL. This is the first step of connecting an account from your server without PyasConnect, and it replaces v1's GET /{provider}/oauth. Send the user to url. With Pyas Auth, the user returns to the Redirect URL you set for this provider under Provider setup, with code and your state. With Native Auth, the user returns to your own callback URL. Then send the code to POST /v2/connect/accounts.
In the sandbox: Connecting signs a real person in to Google, Outlook or Zoom, so it requires a live key. To test connecting in the sandbox, use PyasConnect with a session from POST /v2/connect/sessions, or create virtual accounts with POST /v2/accounts.
Query parameters
- Name
provider- Type
- string
- Required
- required
- Description
google,microsoftorzoom. One ofgoogle,microsoft,zoom.
- Name
state- Type
- string
- Description
Your own value, which is returned to you with the code. For example, use it to identify which of your users is signing in.
- Name
loginHint- Type
- string
- Description
The email address to suggest when the user signs in.
- Name
features- Type
- string
- Description
Additional permissions to request. Accepts a comma-separated list of any of these values: manageCalendars, sharing, meetingSettings, attachmentUploads, rooms.
- Name
redirectUrl- Type
- string
- Description
The callback URL to return the user to, instead of the one under Provider setup. Works only with Native Auth, and your OAuth app must list this URL as a redirect URI.
Errors
VALIDATION_INVALID_QUERY(400): A query parameter is not valid.AUTH_INVALID_KEY(401): The API key is missing, unknown or revoked.AUTH_EXPIRED_KEY(401): The API key has expired.AUTH_SANDBOX_MISMATCH(403): A test key was used with live data, or a live key was used with sandbox data.AUTH_INSUFFICIENT_SCOPE(403): The API key or session does not have permission to make this request.CONNECTION_PROVIDER_NOT_CONFIGURED(422): The app is not configured to connect accounts from this provider.RATE_LIMIT_EXCEEDED(429): The request rate exceeds this plan's rate limit.RATE_LIMIT_BURST(429): Too many requests were sent in a short period.INTERNAL_ERROR(500): Something went wrong on our end.
Request
curl 'https://api.pyas.io/v2/connect/oauth?provider=google&state=user_123&loginHint=person%40example.com' \ -H "x-api-key: $PYAS_API_KEY"Response
{ "success": true, "data": { "provider": "google", "url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=1234567890-pyas.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fapi.pyas.io%2Foauth%2Fgoogle%2Fcallback&response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.events+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.freebusy+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.events.freebusy+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.calendarlist.readonly+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.calendars.readonly+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.settings.readonly&access_type=offline&prompt=consent&include_granted_scopes=true&state=app_id%3D5c1e9a47-2d3b-4f86-a0e9-7b4c2d18f365_rest%3Duser_123&login_hint=person%40example.com" }, "provider": null, "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d", "meta": {}}Create a connect session
Creates a session for connecting a calendar account. This is the first step of connecting with PyasConnect. Call it from your server. With a live key, the user signs in to Google, Microsoft or Zoom and a real account is connected. With a test key, the user sees a Pyas sandbox page instead of the provider's sign-in, and a simulated account is connected in your sandbox, so you can build and test the whole flow before going live. In popup mode, pass the token to your page. In redirect mode, set a returnUrl and send the user to url. A session is valid for 10 minutes and connects one account.
In the sandbox: Pass the token to PyasConnect on your page. With a test key, PyasConnect opens a Pyas sandbox page instead of Google or Microsoft, and connects a simulated account in your sandbox. For redirect mode, add a returnUrl on one of your app's allowed origins. To reconnect a broken account, send its accountId instead of providers and subjectId.
Headers
- Name
Idempotency-Key- Type
- string
- Description
A unique key that makes the request safe to retry. A retry with the same key returns the original response and does not make the change twice. Keys are kept for 24 hours.
Body
- Name
accountId- Type
- string
- Description
The
accountIdof an existing account to reconnect. PyasConnect opens directly to the account's provider, and only the same person (with the same email address) can sign in. The account keeps itsaccountId. Leave outproviders,subjectIdandloginHint, because they are taken from the account.
- Name
providers- Type
- array of string
- Description
The providers to offer the user. Defaults to
googleandmicrosoft. Zoom is offered only when you includezoom. One ofgoogle,microsoft,zoom.
- Name
products- Type
- array of 'calendar'
- Description
What the connection is used for. Currently only
calendaris supported.
- Name
features- Type
- array of string
- Description
Additional permissions to request:
manageCalendars,sharing,meetingSettings,attachmentUploadsorrooms. With Pyas Auth, GooglemanageCalendars,sharing,meetingSettings,attachmentUploadsandroomsneed Native Auth for now. One ofmanageCalendars,sharing,meetingSettings,attachmentUploads,rooms.
- Name
subjectId- Type
- string
- Description
Your own identifier for the connected account.
- Name
loginHint- Type
- string
- Description
The email address to suggest when the user signs in.
- Name
returnUrl- Type
- string
- Description
For redirect mode, the URL to send the user to when the flow ends. Must use HTTPS and be on one of the app's allowed origins.
Errors
VALIDATION_INVALID_BODY(400): The request body is not valid.AUTH_INVALID_KEY(401): The API key is missing, unknown or revoked.AUTH_EXPIRED_KEY(401): The API key has expired.AUTH_ORIGIN_NOT_ALLOWED(403): The request's origin is not in the app's allowed origins.AUTH_INSUFFICIENT_SCOPE(403): The API key or session does not have permission to make this request.CONNECTION_NOT_FOUND(404): No connected account was found for this request.CONNECTION_PROVIDER_NOT_CONFIGURED(422): The app is not configured to connect accounts from this provider.RATE_LIMIT_EXCEEDED(429): The request rate exceeds this plan's rate limit.RATE_LIMIT_BURST(429): Too many requests were sent in a short period.INTERNAL_ERROR(500): Something went wrong on our end.
Request
curl -X POST 'https://api.pyas.io/v2/connect/sessions' \ -H "x-api-key: $PYAS_API_KEY" \ -H "content-type: application/json" \ -d '{ "providers": [ "google", "microsoft" ], "subjectId": "user_123"}'Response
{ "success": true, "data": { "id": "cs_99bec7442c4db29a8539d679", "status": "pending", "mode": "popup", "reconnectAccountId": null, "providers": [ "google", "microsoft" ], "products": [ "calendar" ], "features": [], "subjectId": "user_123", "returnUrl": null, "provider": null, "expiresAt": "2026-11-14T20:10:32.621Z", "account": null, "error": null, "token": "pcs_example", "url": null }, "provider": null, "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d", "meta": {}}Get a connect session
Returns the session's status and the account it connected. In redirect mode, confirm the result with this endpoint rather than relying on the query string.
In the sandbox: Use the ID returned by POST /v2/connect/sessions, with the same kind of key: a session created with a test key is in the sandbox.
Path parameters
- Name
id- Type
- string
- Required
- required
- Description
Errors
AUTH_INVALID_KEY(401): The API key is missing, unknown or revoked.AUTH_EXPIRED_KEY(401): The API key has expired.AUTH_INSUFFICIENT_SCOPE(403): The API key or session does not have permission to make this request.RESOURCE_NOT_FOUND(404): The calendar or event was not found.RATE_LIMIT_EXCEEDED(429): The request rate exceeds this plan's rate limit.RATE_LIMIT_BURST(429): Too many requests were sent in a short period.INTERNAL_ERROR(500): Something went wrong on our end.
Request
curl 'https://api.pyas.io/v2/connect/sessions/cs_0123456789abcdef01234567' \ -H "x-api-key: $PYAS_API_KEY"Response
{ "success": true, "data": { "id": "cs_99bec7442c4db29a8539d679", "status": "pending", "mode": "popup", "reconnectAccountId": null, "providers": [ "google", "microsoft" ], "products": [ "calendar" ], "features": [], "subjectId": "user_123", "returnUrl": null, "provider": null, "expiresAt": "2026-11-14T20:10:32.621Z", "account": null, "error": null }, "provider": null, "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d", "meta": {}}