Accounts

List connected calendar accounts and manage their status, settings and imports, including virtual accounts.


GET/v2/accounts

List accounts

Returns the app's connected accounts and virtual accounts, in the order they were added.

Sends the request to your sandbox, never to live data.

Query parameters

  • Name
    subjectId
    Type
    string
    Description

    Returns only accounts with this subjectId.

  • Name
    provider
    Type
    string
    Description

    One of google, microsoft, zoom, icloud, pyas.

  • Name
    status
    Type
    string
    Description

    One of active, inactive.

  • Name
    limit
    Type
    integer
    Description

    The maximum number of results per page, up to 200. From 1 to 200.

  • Name
    cursor
    Type
    string
    Description

    The nextCursor value from the previous page.

Errors

Request

GET
/v2/accounts
curl 'https://api.pyas.io/v2/accounts?subjectId=sandbox_user_1' \  -H "x-api-key: $PYAS_API_KEY"

Response

200 OK
{  "success": true,  "data": [    {      "accountId": "sbx_fda58c5980_1",      "provider": "pyas",      "email": "sbx_fda58c5980_1@cal.pyas.io",      "name": "Avery Brooks",      "status": "active",      "subjectId": "sandbox_user_1",      "scopes": [],      "createdAt": "2026-11-14T20:00:23.536Z",      "updatedAt": "2026-11-14T20:00:23.536Z"    },    {      "accountId": "sbx_fda58c5980_google",      "provider": "google",      "email": "avery.brooks@example.com",      "name": "Avery Brooks",      "status": "active",      "subjectId": "sandbox_user_1",      "scopes": [        "https://www.googleapis.com/auth/calendar",        "https://www.googleapis.com/auth/calendar.events",        "https://www.googleapis.com/auth/drive.file",        "https://www.googleapis.com/auth/meetings.space.created",        "https://www.googleapis.com/auth/admin.directory.resource.calendar.readonly"      ],      "createdAt": "2026-11-14T20:00:24.196Z",      "updatedAt": "2026-11-14T20:00:24.196Z"    },    {      "accountId": "sbx_fda58c5980_zoom",      "provider": "zoom",      "email": "avery.brooks@example.com",      "name": "Avery Brooks",      "status": "active",      "subjectId": "sandbox_user_1",      "scopes": [        "meeting:write:meeting",        "meeting:read:meeting",        "user:read:user"      ],      "createdAt": "2026-11-14T20:00:24.196Z",      "updatedAt": "2026-11-14T20:00:24.196Z"    }  ],  "provider": null,  "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d",  "meta": {    "nextCursor": null  }}

POST/v2/accounts

Create a virtual account

Creates a calendar account that Pyas hosts itself (provider: pyas), with a primary calendar. Use virtual accounts for people who don't use Google or Outlook, and for testing. Google and Outlook accounts are connected with connect sessions instead.

Sends the request to your sandbox, never to live data.

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
    'pyas'
    Required
    required
    Description
  • Name
    name
    Type
    string
    Required
    required
    Description

    A virtual account's name (1 to 200 characters).

  • Name
    subjectId
    Type
    string
    Description

    Your own identifier for the account.

  • Name
    timezone
    Type
    string
    Description

    An IANA time zone name. Defaults to UTC.

Errors

Request

POST
/v2/accounts
curl -X POST 'https://api.pyas.io/v2/accounts' \  -H "x-api-key: $PYAS_API_KEY" \  -H "content-type: application/json" \  -d '{  "provider": "pyas",  "name": "Taylor Morgan",  "subjectId": "user_123",  "timezone": "America/Chicago"}'

Response

201 Created
{  "success": true,  "data": {    "accountId": "ed449ba9-6b5e-461d-9252-0415a35fddb2",    "provider": "pyas",    "email": "ed449ba9-6b5e-461d-9252-0415a35fddb2@cal.pyas.io",    "name": "Taylor Morgan",    "status": "active",    "subjectId": "user_123",    "scopes": [],    "createdAt": "2026-11-14T20:00:24.652Z",    "updatedAt": "2026-11-14T20:00:24.652Z",    "primaryCalendarId": "calm5p8d0crjk4bdjh6bdts"  },  "provider": "pyas",  "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d",  "meta": {}}

GET/v2/accounts/{accountId}

Get an account

Sends the request to your sandbox, never to live data.

Path parameters

  • Name
    accountId
    Type
    string
    Required
    required
    Description

    The Pyas accountId of the connected account.

Errors

Request

GET
/v2/accounts/{accountId}
curl 'https://api.pyas.io/v2/accounts/sbx_fda58c5980_1' \  -H "x-api-key: $PYAS_API_KEY"

Response

200 OK
{  "success": true,  "data": {    "accountId": "sbx_fda58c5980_1",    "provider": "pyas",    "email": "sbx_fda58c5980_1@cal.pyas.io",    "name": "Avery Brooks",    "status": "active",    "subjectId": "sandbox_user_1",    "scopes": [],    "createdAt": "2026-11-14T20:00:23.536Z",    "updatedAt": "2026-11-14T20:00:23.536Z"  },  "provider": "pyas",  "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d",  "meta": {}}

PATCH/v2/accounts/{accountId}

Update an account

Sets or clears subjectId, your own identifier for the account's user. For a virtual account, you can also update name.

Sends the request to your sandbox, never to live data.

Path parameters

  • Name
    accountId
    Type
    string
    Required
    required
    Description

    The Pyas accountId of the connected account.

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
    subjectId
    Type
    string | null
    Description

    A string to set the identifier, or null to clear it.

  • Name
    name
    Type
    string
    Description

    A virtual account's name (1 to 200 characters).

Errors

Request

PATCH
/v2/accounts/{accountId}
curl -X PATCH 'https://api.pyas.io/v2/accounts/sbx_fda58c5980_2' \  -H "x-api-key: $PYAS_API_KEY" \  -H "content-type: application/json" \  -d '{  "subjectId": "crm_contact_88"}'

Response

200 OK
{  "success": true,  "data": {    "accountId": "sbx_fda58c5980_2",    "provider": "pyas",    "email": "sbx_fda58c5980_2@cal.pyas.io",    "name": "Sam Patel",    "status": "active",    "subjectId": "crm_contact_88",    "scopes": [],    "createdAt": "2026-11-14T20:00:24.847Z",    "updatedAt": "2026-11-14T20:00:25.728Z"  },  "provider": "pyas",  "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d",  "meta": {}}

DELETE/v2/accounts/{accountId}

Delete an account

Deletes an account from your app and sends a connection.deleted webhook.

For a Google, Outlook or Zoom account, Pyas deletes the credentials it stores for the account and stops watching it for changes. The user's calendars at the provider are not changed, and the user can connect the account again later. With a live key, the account no longer counts toward your plan.

A virtual account is deleted with all of its calendars and events.

For every account, the metadata you stored on its events and calendars is deleted too. In the sandbox, resetting the sandbox restores deleted accounts.

In the sandbox: This example deletes the simulated Google account in the sandbox. Virtual accounts are deleted the same way. Resetting the sandbox with POST /v2/sandbox/reset restores deleted sandbox accounts.

Sends the request to your sandbox, never to live data.

Path parameters

  • Name
    accountId
    Type
    string
    Required
    required
    Description

    The Pyas accountId of the connected account.

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.

Errors

Request

DELETE
/v2/accounts/{accountId}
curl -X DELETE 'https://api.pyas.io/v2/accounts/sbx_fda58c5980_google' \  -H "x-api-key: $PYAS_API_KEY"

Response

200 OK
{  "success": true,  "data": null,  "provider": "pyas",  "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d",  "meta": {}}

POST/v2/accounts/import

Import accounts

Imports accounts from another calendar API or from your own integration, so your users don't have to connect their calendars again. Send up to 100 refresh tokens issued to your app's own Google, Microsoft or Zoom OAuth app (Native Auth). Pyas verifies each token with the provider and saves the account. If the account already exists, Pyas updates it with the new tokens. The import runs in the background.

In the sandbox: An import connects real accounts, so it requires a live key. In the sandbox, this request returns AUTH_SANDBOX_MISMATCH.

Sends the request to your sandbox, never to live data.

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
    accounts
    Type
    array of object
    Required
    required
    Description

    At most 100 items.

Errors

Request

POST
/v2/accounts/import
curl -X POST 'https://api.pyas.io/v2/accounts/import' \  -H "x-api-key: $PYAS_API_KEY" \  -H "content-type: application/json" \  -d '{  "accounts": [    {      "provider": "google",      "refreshToken": "1//0g-your-refresh-token",      "subjectId": "user_123"    }  ]}'

Response

202 Accepted
{  "success": true,  "data": {    "id": "aimp_36c11c55818fa0cad686b7d8",    "status": "queued",    "total": 1,    "counts": {      "pending": 1,      "created": 0,      "updated": 0,      "failed": 0    },    "items": [      {        "index": 0,        "provider": "google",        "subjectId": "user_123",        "status": "pending",        "accountId": null,        "email": null,        "error": null      }    ],    "createdAt": "2026-11-14T20:00:32.783Z",    "finishedAt": null  },  "provider": null,  "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d",  "meta": {}}

GET/v2/accounts/imports

List account imports

Sends the request to your sandbox, never to live data.

Query parameters

  • Name
    limit
    Type
    integer
    Description

    The number of imports to return, newest first. Defaults to 20. From 1 to 100.

Errors

Request

GET
/v2/accounts/imports
curl 'https://api.pyas.io/v2/accounts/imports' \  -H "x-api-key: $PYAS_API_KEY"

Response

200 OK
{  "success": true,  "data": [],  "provider": null,  "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d",  "meta": {}}

GET/v2/accounts/status

Get the status of several accounts

Returns the status of each account. overall.status is healthy, attention or broken, and overall includes the reason and the fix. The response also shows which features are available, and includes a message for the account's owner when they need to take action. meta.needsAttention is the number of accounts in the response whose overall.status is not healthy.

With accountIds or subjectId, returns those accounts. Without them, returns every account of the app in the order they were added, one page at a time. To find every account that needs fixing, send overall=attention,broken. A page can include fewer than limit accounts even when meta.nextCursor is set, so keep requesting pages until meta.nextCursor is null. check works only with accountIds or subjectId.

In the sandbox: Lists every account in the app that needs action. In a new sandbox, every account works, so the list is empty. To check particular accounts instead, send accountIds or subjectId.

Sends the request to your sandbox, never to live data.

Query parameters

  • Name
    accountIds
    Type
    string
    Description

    The Pyas accountId values of up to 20 connected accounts. Send a comma-separated list or repeat the parameter.

  • Name
    subjectId
    Type
    string
    Description

    Selects every connected account labeled with this subjectId.

  • Name
    provider
    Type
    string
    Description

    Limits accountIds or subjectId to accounts on this provider. One of google, microsoft, pyas.

  • Name
    overall
    Type
    string
    Description

    Returns only accounts whose overall.status is one of these values, for example attention,broken. Works only without accountIds or subjectId. Accepts a comma-separated list of any of these values: healthy, attention, broken.

  • Name
    limit
    Type
    integer
    Description

    The maximum number of accounts in one page, from 1 to 200. Defaults to 50. Works only without accountIds or subjectId. From 1 to 200.

  • Name
    cursor
    Type
    string
    Description

    The nextCursor from the previous page.

  • Name
    check
    Type
    boolean
    Description

    Sends one request to the provider immediately, bypassing the cache, and includes the result.

Errors

Request

GET
/v2/accounts/status
curl 'https://api.pyas.io/v2/accounts/status?overall=attention%2Cbroken' \  -H "x-api-key: $PYAS_API_KEY"

Response

200 OK
{  "success": true,  "data": [],  "provider": null,  "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d",  "meta": {    "needsAttention": 0,    "nextCursor": null  }}

GET/v2/accounts/{accountId}/settings

Get calendar settings

Returns the person's time zone, locale, week start, time and date format, default event length (Google) and working hours (Outlook). A setting is null when the provider doesn't support it.

Sends the request to your sandbox, never to live data.

Path parameters

  • Name
    accountId
    Type
    string
    Required
    required
    Description

    The Pyas accountId of the connected account.

Errors

Request

GET
/v2/accounts/{accountId}/settings
curl 'https://api.pyas.io/v2/accounts/sbx_fda58c5980_google/settings' \  -H "x-api-key: $PYAS_API_KEY"

Response

200 OK
{  "success": true,  "data": {    "timezone": "America/New_York",    "locale": "en",    "weekStart": "sunday",    "timeFormat": "12h",    "dateOrder": "MDY",    "defaultEventMinutes": 60,    "workingHours": null  },  "provider": "google",  "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d",  "meta": {}}

PATCH/v2/accounts/{accountId}/settings

Update calendar settings

Updates the time zone, time format and working hours (Outlook). The Google Calendar API doesn't support updating settings, so requests for Google accounts return VALIDATION_UNSUPPORTED_OPERATION.

In the sandbox: You can update settings on Outlook accounts. The Google Calendar API supports only reading settings.

Sends the request to your sandbox, never to live data.

Path parameters

  • Name
    accountId
    Type
    string
    Required
    required
    Description

    The Pyas accountId of the connected account.

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
    timezone
    Type
    string
    Description

    An IANA time zone name, such as America/New_York.

  • Name
    timeFormat
    Type
    string
    Description

    One of 12h, 24h.

  • Name
    workingHours
    Type
    object
    Description
  • Name
    workingHours.days
    Type
    array of string
    Required
    required
    Description

    One of sunday, monday, tuesday, wednesday, thursday, friday, saturday.

  • Name
    workingHours.start
    Type
    string
    Required
    required
    Description
  • Name
    workingHours.end
    Type
    string
    Required
    required
    Description
  • Name
    workingHours.timezone
    Type
    string
    Required
    required
    Description

Errors

Request

PATCH
/v2/accounts/{accountId}/settings
curl -X PATCH 'https://api.pyas.io/v2/accounts/sbx_fda58c5980_outlook/settings' \  -H "x-api-key: $PYAS_API_KEY" \  -H "content-type: application/json" \  -d '{  "timezone": "Europe/Paris",  "timeFormat": "24h"}'

Response

200 OK
{  "success": true,  "data": {    "timezone": "Europe/Paris",    "locale": "en-GB",    "weekStart": null,    "timeFormat": "24h",    "dateOrder": null,    "defaultEventMinutes": null,    "workingHours": {      "days": [        "monday",        "tuesday",        "wednesday",        "thursday",        "friday"      ],      "start": "09:00",      "end": "17:30",      "timezone": "Europe/London"    }  },  "provider": "microsoft",  "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d",  "meta": {}}

GET/v2/accounts/{accountId}/status

Get the status of an account

Returns the status of the account. state shows whether the account is connected, and health is based on its recent provider requests. The response also shows whether each feature is available, which permissions are missing and what the provider supports, and includes a message for the account's owner when they need to take action.

Sends the request to your sandbox, never to live data.

Path parameters

  • Name
    accountId
    Type
    string
    Required
    required
    Description

    The Pyas accountId of the connected account.

Query parameters

  • Name
    check
    Type
    boolean
    Description

    Sends one request to the provider immediately, bypassing the cache, and includes the result.

Errors

Request

GET
/v2/accounts/{accountId}/status
curl 'https://api.pyas.io/v2/accounts/sbx_fda58c5980_1/status?check=true' \  -H "x-api-key: $PYAS_API_KEY"

Response

200 OK
{  "success": true,  "data": {    "accountId": "sbx_fda58c5980_1",    "provider": "pyas",    "name": "Avery Brooks",    "email": "sbx_fda58c5980_1@cal.pyas.io",    "subjectId": "sandbox_user_1",    "state": "connected",    "health": {      "status": "unknown",      "lastSuccessAt": null,      "lastFailure": null    },    "scopes": {      "recorded": [],      "source": "requestedAtConnect"    },    "features": {      "readEvents": {        "available": true      },      "writeEvents": {        "available": true      },      "manageCalendars": {        "available": true      },      "freeBusy": {        "available": true      },      "sync": {        "available": true      },      "sharing": {        "available": false,        "reason": "Virtual calendars are shared through their subscription feed, not with individual people."      },      "settings": {        "available": true      },      "changeSettings": {        "available": true      },      "categories": {        "available": true      },      "meetingSettings": {        "available": false,        "reason": "Virtual calendars use Zoom links created through a connected Zoom account. They have no meeting settings of their own."      },      "attachmentUploads": {        "available": false,        "reason": "Virtual calendars store links, not files."      },      "rooms": {        "available": false,        "reason": "Virtual accounts have no room directory."      }    },    "capabilities": {      "incrementalSync": true,      "freeBusy": true,      "batch": false,      "nativeMetadata": false,      "calendarWrite": true,      "maxAttachmentBytes": 0,      "push": {        "supported": false,        "maxTtlSeconds": 0      }    },    "userMessage": null,    "fixUrl": null,    "overall": {      "status": "healthy",      "reason": null,      "fix": null    },    "check": {      "ok": true,      "at": "2026-11-14T20:00:24.415Z"    }  },  "provider": "pyas",  "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d",  "meta": {}}

GET/v2/accounts/{accountId}/working-locations

List working locations

Returns where the person works each day, from Google's working location events (home, office or elsewhere). The window can span at most 92 days.

Sends the request to your sandbox, never to live data.

Path parameters

  • Name
    accountId
    Type
    string
    Required
    required
    Description

    The Pyas accountId of the connected account.

Query parameters

  • Name
    from
    Type
    string (date-time)
    Description

    An ISO 8601 time with a zone.

  • Name
    to
    Type
    string (date-time)
    Description

    An ISO 8601 time with a zone.

Errors

Request

GET
/v2/accounts/{accountId}/working-locations
curl 'https://api.pyas.io/v2/accounts/sbx_fda58c5980_google/working-locations?from=2026-11-14T00%3A00%3A00Z&to=2026-11-28T00%3A00%3A00Z' \  -H "x-api-key: $PYAS_API_KEY"

Response

200 OK
{  "success": true,  "data": [    {      "eventId": "sgcd2d8976578edb2f608c814d",      "startsAt": "2026-11-15T05:00:00Z",      "endsAt": "2026-11-16T05:00:00Z",      "isAllDay": true,      "location": {        "type": "office",        "label": "HQ"      }    },    {      "eventId": "sg69e86df5bfd6e93979271e83",      "startsAt": "2026-11-16T05:00:00Z",      "endsAt": "2026-11-17T05:00:00Z",      "isAllDay": true,      "location": {        "type": "home",        "label": null      }    }  ],  "provider": "google",  "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d",  "meta": {}}

GET/v2/accounts/imports/{importId}

Get an account import

In the sandbox: Use the ID returned by POST /v2/accounts/import.

Sends the request to your sandbox, never to live data.

Path parameters

  • Name
    importId
    Type
    string
    Required
    required
    Description

Errors

Request

GET
/v2/accounts/imports/{importId}
curl 'https://api.pyas.io/v2/accounts/imports/aimp_0123456789abcdef01234567' \  -H "x-api-key: $PYAS_API_KEY"

Response

200 OK
{  "success": true,  "data": {    "id": "aimp_36c11c55818fa0cad686b7d8",    "status": "done",    "total": 1,    "counts": {      "pending": 0,      "created": 1,      "updated": 0,      "failed": 0    },    "items": [      {        "index": 0,        "provider": "google",        "subjectId": "user_123",        "status": "created",        "accountId": "00d34c15-3251-490a-a8ff-01c8ce8de35d",        "email": "refresh@example.test",        "error": null      }    ],    "createdAt": "2026-11-14T20:00:32.783Z",    "finishedAt": "2026-11-14T20:00:32.879Z"  },  "provider": null,  "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d",  "meta": {}}

POST/v2/accounts/imports/{importId}/retry

Retry an account import

Retries the accounts that failed with an error that may since have been resolved, such as an unavailable provider or a plan that had reached its connected account limit.

In the sandbox: Use the ID returned by POST /v2/accounts/import.

Sends the request to your sandbox, never to live data.

Path parameters

  • Name
    importId
    Type
    string
    Required
    required
    Description

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.

Errors

Request

POST
/v2/accounts/imports/{importId}/retry
curl -X POST 'https://api.pyas.io/v2/accounts/imports/aimp_0123456789abcdef01234567/retry' \  -H "x-api-key: $PYAS_API_KEY"

Response

202 Accepted
{  "success": true,  "data": {    "id": "aimp_36766aa0cea9fddd52b0fb7d",    "status": "queued",    "total": 1,    "counts": {      "pending": 1,      "created": 0,      "updated": 0,      "failed": 0    },    "items": [      {        "index": 0,        "provider": "google",        "subjectId": "user_456",        "status": "pending",        "accountId": null,        "email": null,        "error": null      }    ],    "createdAt": "2026-11-14T20:00:32.884Z",    "finishedAt": null  },  "provider": null,  "traceId": "trc_5f2a9c1e7b3d4a6f8e0c2b1d",  "meta": {}}