OAuth with Zoom

The Zoom API uses OAuth 2.0 to authenticate and authorize users to make requests. To set up access credentials and request scopes for your app, create an OAuth app on the Marketplace. Follow the Create an OAuth App guide for a full walkthrough.

OAuth2 endpoints are located at https://zoom.us/oauth/.

All Zoom OAuth and API endpoints must be called from the server side of your application. If called from the client side, CORS errors will be thrown.

On This Page

Getting an access token

To get an access token, you'll set scopes for the level of access that your app needs from the user. Zoom presents information about these scopes and access requests to the user. The user will Authorize or Decline these access permissions for your app. See OAuth Scopes for details.

Once the user Authorizes the scopes, your app can request an access token. To retain this access level, your app can request refesh tokens.

Follow the steps below to request access.

Step 1: Request user authorization

Direct the user to https://zoom.us/oauth/authorize with the following query parameters:

Query ParameterDescription
response_typeAccess response type being requested. The supported authorization workflow requires the value code.
redirect_uriURI to handle successful user authorization. Must match with Development or Production Redirect URI in your OAuth app settings.
client_idOAuth application's Development or Production Client ID.
state(Optional) An opaque value that you can use to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the your app.
code_challenge(Optional, but required if using PKCE) A challenge derived from the code verifier sent in the authorization request to verify against the code_verifier later.
code_challenge_method(Optional) A method that was used to derive the code challenge. Defaults to "plain" if not present in the request. Code verifier transformation method is "S256" or "plain".

An example without optional parameters:

https://zoom.us/oauth/authorize?response_type=code&client_id=7lstjK9NTyett_oeXtFiEQ&redirect_uri=https://yourapp.example.com

This URL is the same as the Add Button link on the Zoom App Marketplace.

If this is the first time that you are requesting authorization from a user, the user will be prompted by Zoom to authorize access for your app.

If authorized, the user will be redirected to the redirect_uri with the authorization code in the code query parameter.

https://yourapp.com/?code=obBEe8ewaL_KdyNjniT4KPd8ffDWt9fGB

Set the scopes for your app in the Zoom App Marketplace. See Set Scopes for details.

Preserving User State in Redirect URLs

To provide users context in your app when they are adding the app, attach a state query parameter to the redirect_uri parameter of the add link. When the user is returned to your app, the state parameter will be included along with the authorization code.

For example:

https://zoom.us/oauth/authorize?response_type=code&client_id=7lstjK9NTyett_oeXtFiEQ&redirect_uri=https://yourapp.com&state={userState}

This would redirect the user to:

https://yourapp.com?state={userState}&code=obBEe8ewaL_KdyNjniT4KPd8ffDWt9fGB

Using Proof Key for Code Exchange (PKCE)

Zoom supports Proof Key for Code Exchange (PKCE) when requesting user tokens. This offers better security by enabling clients to use a code challenge and code exchange as part of the initial user authorization request. See rfc7636 for more information.

To use this feature, send the code_challenge field and optional code_challenge_method field in the user Authorization request. Then send the code_verifier field in the request access token step.

If Zoom verifies that the code_challenge and the code_verifier values match, the token endpoint continues processing. If they do not match, you will receive an invalid_grant error.

Step 2: Request access token

Make a POST request to https://zoom.us/oauth/token with the following Request Headers and Request Body information:

HTTP Request Headers

HeaderDescription
AuthorizationThe string Basic with your Client ID and Client Secret separated with colon (:), Base64-encoded. For example, Client_ID:Client_Secret Base64-encoded is Q2xpZW50X0lEOkNsaWVudF9TZWNyZXQ=.
Content-Typeapplication/x-www-form-urlencoded

Request Body

Request parameterDescription
codeThe authorization code supplied to the callback by Zoom.
grant_typeauthorization_code
redirect_uriYour application's redirect URI.
code_verifierOptional, but required if using PKCE. A cryptographically random string used to correlate the authorization request to the token request.

Be sure to pass the code, grant_type, redirect_uri and code_verifier in the request body and not as path parameters. Example request body:

POST https://zoom.us/oauth/token
HTTP/1.1

# Header
Host: zoom.us
Authorization: Basic Q2xpZW50X0lEOkNsaWVudF9TZWNyZXQ=
Content-Type: application/x-www-form-urlencoded

# Request body
code: [CODE]
grant_type: authorization_code
redirect_uri: [REDIRECT URI]
code_verifier: [CODE VERIFIER]

If successful, the response body is a JSON response containing the user's access token:

{
  "access_token": "eyJhbGciOiJIUzUxMiIsInYiOiIyLjAiLCJraWQiOiI8S0lEPiJ9.eyJ2ZXIiOiI2IiwiY2xpZW50SWQiOiI8Q2xpZW50X0lEPiIsImNvZGUiOiI8Q29kZT4iLCJpc3MiOiJ1cm46em9vbTpjb25uZWN0OmNsaWVudGlkOjxDbGllbnRfSUQ-IiwiYXV0aGVudGljYXRpb25JZCI6IjxBdXRoZW50aWNhdGlvbl9JRD4iLCJ1c2VySWQiOiI8VXNlcl9JRD4iLCJncm91cE51bWJlciI6MCwiYXVkIjoiaHR0cHM6Ly9vYXV0aC56b29tLnVzIiwiYWNjb3VudElkIjoiPEFjY291bnRfSUQ-IiwibmJmIjoxNTgwMTQ2OTkzLCJleHAiOjE1ODAxNTA1OTMsInRva2VuVHlwZSI6ImFjY2Vzc190b2tlbiIsImlhdCI6MTU4MDE0Njk5MywianRpIjoiPEpUST4iLCJ0b2xlcmFuY2VJZCI6MjV9.F9o_w7_lde4Jlmk_yspIlDc-6QGmVrCbe_6El-xrZehnMx7qyoZPUzyuNAKUKcHfbdZa6Q4QBSvpd6eIFXvjHw",
  "token_type": "bearer",
  "refresh_token": "eyJhbGciOiJIUzUxMiIsInYiOiIyLjAiLCJraWQiOiI8S0lEPiJ9.eyJ2ZXIiOiI2IiwiY2xpZW50SWQiOiI8Q2xpZW50X0lEPiIsImNvZGUiOiI8Q29kZT4iLCJpc3MiOiJ1cm46em9vbTpjb25uZWN0OmNsaWVudGlkOjxDbGllbnRfSUQ-IiwiYXV0aGVudGljYXRpb25JZCI6IjxBdXRoZW50aWNhdGlvbl9JRD4iLCJ1c2VySWQiOiI8VXNlcl9JRD4iLCJncm91cE51bWJlciI6MCwiYXVkIjoiaHR0cHM6Ly9vYXV0aC56b29tLnVzIiwiYWNjb3VudElkIjoiPEFjY291bnRfSUQ-IiwibmJmIjoxNTgwMTQ2OTkzLCJleHAiOjIwNTMxODY5OTMsInRva2VuVHlwZSI6InJlZnJlc2hfdG9rZW4iLCJpYXQiOjE1ODAxNDY5OTMsImp0aSI6IjxKVEk-IiwidG9sZXJhbmNlSWQiOjI1fQ.Xcn_1i_tE6n-wy6_-3JZArIEbiP4AS3paSD0hzb0OZwvYSf-iebQBr0Nucupe57HUDB5NfR9VuyvQ3b74qZAfA",
  "expires_in": 3599,
  "scope": "user:read:admin"
}

You can use this access token to make requests to the Zoom API. Access tokens expire after one hour.

Using an access token

Make requests to the Zoom API by sending the access_token as the Authorization Bearer header.

"Authorization": "Bearer <ACCESS_TOKEN>"

Example Request

GET

https://api.zoom.us/v2/users/me

Note: This endpoint uses the /me context.

Request Headers

{
  "Authorization": "Bearer eyJhbGciOiJIUzUxMiIsInYiOiIyLjAiLCJraWQiOiI8S0lEPiJ9.eyJ2ZXIiOiI2IiwiY2xpZW50SWQiOiI8Q2xpZW50X0lEPiIsImNvZGUiOiI8Q29kZT4iLCJpc3MiOiJ1cm46em9vbTpjb25uZWN0OmNsaWVudGlkOjxDbGllbnRfSUQ-IiwiYXV0aGVudGljYXRpb25JZCI6IjxBdXRoZW50aWNhdGlvbl9JRD4iLCJ1c2VySWQiOiI8VXNlcl9JRD4iLCJncm91cE51bWJlciI6MCwiYXVkIjoiaHR0cHM6Ly9vYXV0aC56b29tLnVzIiwiYWNjb3VudElkIjoiPEFjY291bnRfSUQ-IiwibmJmIjoxNTgwMTQ2OTkzLCJleHAiOjE1ODAxNTA1OTMsInRva2VuVHlwZSI6ImFjY2Vzc190b2tlbiIsImlhdCI6MTU4MDE0Njk5MywianRpIjoiPEpUST4iLCJ0b2xlcmFuY2VJZCI6MjV9.F9o_w7_lde4Jlmk_yspIlDc-6QGmVrCbe_6El-xrZehnMx7qyoZPUzyuNAKUKcHfbdZa6Q4QBSvpd6eIFXvjHw"
}

If successful, the response body will be a JSON representation of your user:

{
  "id": "KdYKjnimT4KPd8FFgQt9FQ",
  "first_name": "Jane",
  "last_name": "Dev",
  "email": "jane.dev@email.com",
  "type": 2,
  "role_name": "Owner",
  "pmi": 1234567890,
  "use_pmi": false,
  "vanity_url": "https://janedevinc.zoom.us/my/janedev",
  "personal_meeting_url": "https://janedevinc.zoom.us/j/1234567890",
  "timezone": "America/Denver",
  "verified": 1,
  "dept": "",
  "created_at": "2019-04-05T15:24:32Z",
  "last_login_time": "2019-12-16T18:02:48Z",
  "last_client_version": "4.6.12611.1124(mac)",
  "pic_url": "https://janedev.zoom.us/p/KdYKjnimFR5Td8KKdQt9FQ/19f6430f-ca72-4154-8998-ede6be4542c7-837",
  "host_key": "533895",
  "jid": "kdykjnimt4kpd8kkdqt9fq@xmpp.zoom.us",
  "group_ids": [],
  "im_group_ids": ["3NXCD9VFTCOUH8LD-QciGw"],
  "account_id": "gVcjZnYYRLDbb_MfgHuaxg",
  "language": "en-US",
  "phone_country": "US",
  "phone_number": "+1 1234567891",
  "status": "active"
}

Refreshing an access token

Access tokens expire after one hour. Once expired, you will have to refresh a user's access token.

Make a POST request to https://zoom.us/oauth/token with the following HTTP request headers and request body:

Authorization HeaderDescription
AuthorizationThe string "Basic" with your Client ID and Client Secret with a colon (:) in between, Base64-encoded. For example, Client_ID:Client_Secret Base64-encoded is Q2xpZW50X0lEOkNsaWVudF9TZWNyZXQ=.
Content-Typeapplication/x-www-form-urlencoded
Request ParameterDescription
grant_typerefresh_token
refresh_tokenYour refresh token.

Request

Here's an example request for a refresh token:

POST https://zoom.us/oauth/token
HTTP/1.1
Host: zoom.us
Authorization: Basic base64Encode(client_id:client_secret)
Content-Type: application/x-www-form-urlencoded

refresh_token=[REFRESH TOKEN]&grant_type=refresh_token

Response

If successful, the response body will be a JSON representation of your user's refreshed access token:

{
  "access_token": "eyJhbGciOiJIUzUxMiIsInYiOiIyLjAiLCJraWQiOiI8S0lEPiJ9.eyJ2ZXIiOiI2IiwiY2xpZW50SWQiOiI8Q2xpZW50X0lEPiIsImNvZGUiOiI8Q29kZT4iLCJpc3MiOiJ1cm46em9vbTpjb25uZWN0OmNsaWVudGlkOjxDbGllbnRfSUQ-IiwiYXV0aGVudGljYXRpb25JZCI6IjxBdXRoZW50aWNhdGlvbl9JRD4iLCJ1c2VySWQiOiI8VXNlcl9JRD4iLCJncm91cE51bWJlciI6MCwiYXVkIjoiaHR0cHM6Ly9vYXV0aC56b29tLnVzIiwiYWNjb3VudElkIjoiPEFjY291bnRfSUQ-IiwibmJmIjoxNTgwMTQ3Mzk0LCJleHAiOjE1ODAxNTA5OTQsInRva2VuVHlwZSI6ImFjY2Vzc190b2tlbiIsImlhdCI6MTU4MDE0NzM5NCwianRpIjoiPEpUST4iLCJ0b2xlcmFuY2VJZCI6MjZ9.5c58p0PflZJdlz4Y7PgMIVCrQpHDnbM565iCKlrtajZ5HHmy00P5FCcoMwHb9LxjsUgbJ7653EfdeX5NEm6RoA",
  "token_type": "bearer",
  "refresh_token": "eyJhbGciOiJIUzUxMiIsInYiOiIyLjAiLCJraWQiOiI8S0lEPiJ9.eyJ2ZXIiOiI2IiwiY2xpZW50SWQiOiI8Q2xpZW50X0lEPiIsImNvZGUiOiI8Q29kZT4iLCJpc3MiOiJ1cm46em9vbTpjb25uZWN0OmNsaWVudGlkOjxDbGllbnRfSUQ-IiwiYXV0aGVudGljYXRpb25JZCI6IjxBdXRoZW50aWNhdGlvbl9JRD4iLCJ1c2VySWQiOiI8VXNlcl9JRD4iLCJncm91cE51bWJlciI6MCwiYXVkIjoiaHR0cHM6Ly9vYXV0aC56b29tLnVzIiwiYWNjb3VudElkIjoiPEFjY291bnRfSUQ-IiwibmJmIjoxNTgwMTQ3Mzk0LCJleHAiOjIwNTMxODczOTQsInRva2VuVHlwZSI6InJlZnJlc2hfdG9rZW4iLCJpYXQiOjE1ODAxNDczOTQsImp0aSI6IjxKVEk-IiwidG9sZXJhbmNlSWQiOjI2fQ.DwuqOzywRrQO2a6yp0K_6V-hR_i_mOB62flkr0_NfFdYsSqahIRRGk1GlUTQnFzHd896XDKf_FnSSvoJg_tzuQ",
  "expires_in": 3599,
  "scope": "user:read"
}

Refresh tokens expire after 15 years. The latest refresh token must always be used for the next refresh request.

Revoking an access token

To revoke a users access token, make a POST request to https://zoom.us/oauth/revoke with the following request body parameter and authorization headers:

ParameterDescription
tokenThe current access token to revoke that is valid and not expired.
Authorization HeaderDescription
AuthorizationThe string "Basic" with your Client ID and Client Secret with a colon (:) in between, Base64-encoded. For example, Client_ID:Client_Secret Base64-encoded is Q2xpZW50X0lEOkNsaWVudF9TZWNyZXQ=.
Content-Typeapplication/x-www-form-urlencoded

Request

Here's an example request to revoke an access token:

POST /oauth/revoke HTTP/1.1
Host: zoom.us
Authorization: Basic base64Encode(client_id:client_secret)
Content-Type: application/x-www-form-urlencoded; charset=UTF-8 4

token=[ACCESS TOKEN]

Response

If successful, the response body will be a JSON success object:

{
  "status": "success"
}

Advanced Practices

Preserving User State in Redirect URLs

When directing a user to authorize your app, attach a state query parameter to the add link. When the user is returned to your app, the state parameter will be included along with the authorization code.

Example:

https://zoom.us/oauth/authorize?response_type=code&client_id=7lstjK9NTyett_oeXtFiEQ&state=<userstate>&redirect_uri=https://yourapp.com

This would redirect the user to:

https://yourapp.com/?code=obBEe8ewaL_KdyNjniT4KPd8ffDWt9fGB&state=<userstate>

Using Multiple Environments

To support multiple subdomain environments for your users, add any as the subdomain of your Redirect URL (development & production). Example: https://any.yourapp.com.

In your add link, dynamically set the respective subdomain on the redirect_uri param:

For https://sub1.yourapp.com:

https://zoom.us/oauth/authorize?response_type=code&client_id=7lstjK9NTyett_oeXtFiEQ&redirect_uri=https://sub1.yourapp.com

For https://sub2.yourapp.com:

https://zoom.us/oauth/authorize?response_type=code&client_id=7lstjK9NTyett_oeXtFiEQ&redirect_uri=https://sub2.yourapp.com

The /me Context

For APIs where OAuth is available, you can replace the {userID} path parameter with me to restrict the context of the call to the user the token belongs to. This is a quick way to use user-specific endpoints instead of needing to lookup or store the user ID for each token.

Below is a list of requests which support the /me context:

URLMethods
/v2/users/meGET, PATCH
/v2/users/me/tokenGET, DELETE
/v2/users/me/settingsGET, PATCH
/v2/users/me/meetingsGET, POST
/v2/users/me/webinarsGET, POST
/v2/users/me/recordingsGET
/v2/users/me/assistantsGET, POST, DELETE
/v2/users/me/assistants/{assistantId}DELETE

OAuth with Chatbots

Account-level OAuth apps can also be Chatbot apps, just as Chatbot apps can be account-level OAuth apps; however, OAuth apps and Chatbots have a different authentication flows.

Combining OAuth and Chatbot functionality into one app will require you to implement two authorization flows for both OAuth and Chatbot tokens.

Requesting an OAuth and Chatbot Token

Direct the user to https://zoom.us/oauth/authorize with the following query parameters:

Query ParameterDescription
response_typeAccess response type being requested. The supported authorization workflow requires the value code.
redirect_uriURI to handle successful user authorization. Must match with Development or Production Redirect URI in your OAuth app settings.
client_idOAuth application's Development or Production Client ID.

Example

https://zoom.us/oauth/authorize?response_type=code&client_id=U1RqQ9UsQo6hd6fJQWFLQ&redirect_uri=https://yourapp.com

This URL is the same as the Add Button link on the Zoom App Marketplace.

If this is the first time that you are requesting authorization from a user, the user will be prompted by Zoom to authorize access for your app.

If authorized, the user will be redirected to the redirect_uri with the authorization code in the code query parameter.

https://yourapp.com/?code=obBEe8ewaL_KdyNjniT4KPd8ffDWt9fGB

Notice the code returned in the redirect URL. Follow Step 2 in Requesting an access token to obtain an OAuth access token.

To get a Chatbot token, make a POST request to https://zoom.us/oauth/token with the following query parameters and authorization header:

Query ParameterDescription
grant_typeValue client_credentials.
Authorization HeaderDescription
AuthorizationThe string "Basic" with your Client ID and Client Secret with a colon (:) in between, Base64-encoded. For example, Client_ID:Client_Secret Base64-encoded is Q2xpZW50X0lEOkNsaWVudF9TZWNyZXQ=.

Example Request

POST

https://zoom.us/oauth/token?grant_type=client_credentials

Request Headers

{
  "Authorization": "Basic Q2xpZW50X0lEOkNsaWVudF9TZWNyZXQ="
}

If successful, the response body will be a JSON representation of the Chatbot token:

{
  "access_token": "eyJhbGciOiJIUzUxMiIsInYiOiIyLjAiLCJraWQiOiI8S0lEPiJ9.eyJhdWQiOiJodHRwczovL29hdXRoLnpvb20udXMiLCJ2ZXIiOiI2IiwibmJmIjoxNTgwMTQ2NjkzLCJjbGllbnRJZCI6IjxDbGllbnRfSUQ-IiwiaXNzIjoidXJuOnpvb206Y29ubmVjdDpjbGllbnRpZDo8Q2xpZW50X0lEPiIsImF1dGhlbnRpY2F0aW9uSWQiOiI8QXV0aGVudGljYXRpb25fSUQ-IiwiZXhwIjoxNTgwMTUwMjkzLCJ0b2tlblR5cGUiOiJjbGllbnRfdG9rZW4iLCJpYXQiOjE1ODAxNDY2OTMsInVzZXJJZCI6IjxVc2VyX0lEPiIsImdyb3VwTnVtYmVyIjowLCJqdGkiOiI8SlRJPiJ9.chgzEaGxeYl3alAaLsFSRvQFVRqoabM5BINVELOYPO1FqveoEk02i8AIGrtg0FiX779pMWpMObkxFnPQy7euNA",
  "token_type": "bearer",
  "expires_in": 3599,
  "scope": "imchat:bot"
}

Chatbot tokens expire after one hour.

Using a Chatbot Token

Make requests to the Chatbot API by sending the Chatbot token as the Authorization Bearer header:

"Authorization": "Bearer <CHATBOT_TOKEN>"

Example Request

POST

https://api.zoom.us/v2/im/chat/messages

Request Headers

{
  "Authorization": "Bearer eyJhbGciOiJIUzUxMiIsInYiOiIyLjAiLCJraWQiOiI8S0lEPiJ9.eyJhdWQiOiJodHRwczovL29hdXRoLnpvb20udXMiLCJ2ZXIiOiI2IiwibmJmIjoxNTgwMTQ2NjkzLCJjbGllbnRJZCI6IjxDbGllbnRfSUQ-IiwiaXNzIjoidXJuOnpvb206Y29ubmVjdDpjbGllbnRpZDo8Q2xpZW50X0lEPiIsImF1dGhlbnRpY2F0aW9uSWQiOiI8QXV0aGVudGljYXRpb25fSUQ-IiwiZXhwIjoxNTgwMTUwMjkzLCJ0b2tlblR5cGUiOiJjbGllbnRfdG9rZW4iLCJpYXQiOjE1ODAxNDY2OTMsInVzZXJJZCI6IjxVc2VyX0lEPiIsImdyb3VwTnVtYmVyIjowLCJqdGkiOiI8SlRJPiJ9.chgzEaGxeYl3alAaLsFSRvQFVRqoabM5BINVELOYPO1FqveoEk02i8AIGrtg0FiX779pMWpMObkxFnPQy7euNA"
}

Request Body

{
  "robot_jid": "v1zx6cy00psoylshypvg-iuq@xmpp.zoom.us",
  "to_jid": "kdykjnimt4kpd8kkdqt9fq@xmpp.zoom.us",
  "account_id": "gVcjZnWWRLWvv_GtyGuaxg",
  "content": {
    "head": {
      "text": "Hello World"
    }
  }
}

If successful, the response body will be a JSON representation of the sent Chatbot message:

{
  "message_id": "20191218175454248_UvRlxOz_aw1",
  "robot_jid": "v1zx6cy00psoylshypvg-iuq@xmpp.zoom.us",
  "sent_time": "2019-12-18 17:54:54",
  "to_jid": "kdykjnimt4kpd8kkdqt9fq@xmpp.zoom.us"
}
Chatbot Message

Refreshing a Chatbot Token

Refreshing a Chatbot token is the same process as requesting a Chatbot token. Make a POST request to https://zoom.us/oauth/token with the following query parameters and authorization header:

Query ParameterDescription
grant_typeValue client_credentials.
Authorization HeaderDescription
AuthorizationThe string "Basic" with your Client ID and Client Secret with a colon (:) in between, Base64-encoded. For example, Client_ID:Client_Secret Base64-encoded is Q2xpZW50X0lEOkNsaWVudF9TZWNyZXQ=.

Example Request

POST

https://zoom.us/oauth/token?grant_type=client_credentials

Request Headers

{
  "Authorization": "Basic Q2xpZW50X0lEOkNsaWVudF9TZWNyZXQ="
}

If successful, the response body will be a JSON representation of your refreshed Chatbot token:

{
  "access_token": "eyJhbGciOiJIUzUxMiIsInYiOiIyLjAiLCJraWQiOiI8S0lEPiJ9.eyJhdWQiOiJodHRwczovL29hdXRoLnpvb20udXMiLCJ2ZXIiOiI2IiwibmJmIjoxNTgwMTQ2NjkzLCJjbGllbnRJZCI6IjxDbGllbnRfSUQ-IiwiaXNzIjoidXJuOnpvb206Y29ubmVjdDpjbGllbnRpZDo8Q2xpZW50X0lEPiIsImF1dGhlbnRpY2F0aW9uSWQiOiI8QXV0aGVudGljYXRpb25fSUQ-IiwiZXhwIjoxNTgwMTUwMjkzLCJ0b2tlblR5cGUiOiJjbGllbnRfdG9rZW4iLCJpYXQiOjE1ODAxNDY2OTMsInVzZXJJZCI6IjxVc2VyX0lEPiIsImdyb3VwTnVtYmVyIjowLCJqdGkiOiI8SlRJPiJ9.chgzEaGxeYl3alAaLsFSRvQFVRqoabM5BINVELOYPO1FqveoEk02i8AIGrtg0FiX779pMWpMObkxFnPQy7euNA",
  "token_type": "bearer",
  "expires_in": 3599,
  "scope": "imchat:bot"
}

Chatbot tokens expire after one hour.

Need help?

If you're looking for help, try Developer Support or our Developer Forum. Priority support is also available with Premier Developer Support plans.