Example by steps

Let’s take a look at the full process of getting access to data, beginning from the registration of a new integration. While at it we will also discuss the direct work with authorization API, but you can use our premade PHP library to simplify development or premade libraries from other vendors, which you can find by following this link

We developed the authorization on the base of the oAuth 2.0 protocol, that’s why you can find in open source a lot of examples and documentation, that describes the logic of making requests.

1. Registration of an Application

It all begins with you going to Settings, Integrations of the account, in which you will support the integration in the future.

Please note: This account will be the main one for your Integration. It means that any administrator of that account can manage the integration and get access to the common keys of an application. You can check the terminology here. Such an account will be treated by us as a developer account.

To create an integration you need administrator rights on the account.

After clicking on the button Create Integration in the interface of the opened window you need to indicate the Integration name, select Allow access and indicate the Integration description. You also need to indicate the Redirect URl – url of the page of getting tokens and upload the logo of the Integration.

  • Name of the Integration (Not more than 255 symbols) – displayed on the page of Integrations, the modal window of granted access and also in the search on the Integrations page.
  • Description of the Integration (Not more than 65000 symbols) – displayed in the modal window of the integration. You can use HTML layout.
  • Redirect URl – link your site, which will be working with keys. It’s important that the domain would be protected with an SSL certificate, if you plan to use the integration in more than one account. Also, we periodically check the accessibility of the domain, as required for the integration to work.
  • Allow access – minimum set of required permissions for an integration to work. More details explained in this article here.
  • Icon of the integration (400×272 jpeg/jpg/png/gif) – displayed in the integrations page and in the window for getting access from the user.

Except for these administrators of the account, in which the integration was created it will also have: ID of integration, Secret key of integration, Authorization code.

After filling out the form you’ll need to click on Generate key. After that the new integration will be created and on the next page of the modal window, you will see all the required keys.

Please note: The Secret key and Integration ID connected to the integration will show up only in your developer account.

2. Getting an Authorization code

Let us remind you that this is a key with a limited life-span (20 minutes) and with the help of it, you need to get a refresh token and access token before it’s lifespan runs out. It has a limited life-span because it can be stolen, but if stolen nothing can be done with it if the one who stole your Authorization code doesn’t have the keys of the application, that are known only to account administrators, in which the integration was created.

You can get the Authorization code in three ways:

  1. Copy from the modal window of the installed integration. This will work if you need to integrate only one account of amoCRM. Please check more on the question in Simplified Authorization.
  2. If your integration has a widget, then after installing it you will have a webhook sent to the Redirect URl
  3. Get the code after the user gets redirected to the Redirect URl

You can simplify development when getting a key via GET-parameters with the button amoCRM.

The full logic on how to get a key via GET-parameters is explained below:

  1. User, from which you need to get access from, on your site opens the link that you send to them Attention: It’s really important that for the user the whole process is understandable. When users click on the link, they need to understand that the request of the permissions will happen in their amoCRM account and they need to understand which integration they are trying to install.
  2. That’s why we suggest that you use our branded button, a description of which you can find by this link Button.

  3. Generation of the link, which users need to go to. You need to send a user to URL https://www.amocrm.com/oauth?client_id={Integration ID}&state={parameter of the state, that will be sent to you to Redirect URl}&mode={popup or post_message}.
    Integration ID is already known to you. State – generated by your string parameter, maybe your hash. After getting a response from amoCRM State it is required for you to check the credibility of it, by checking the sent key and the one that is generated as a result, make sure that there is no replacement of CSRF. Parameter mode is required for the processing of the request to Redirect URl. In the popup method – the window of the authorization will be closed, and redirect to the Redirect URl will happen in the main window. In the post_message method, the redirection will happen in the window that was opened, after processing the code of Authorization, you’ll need to close the window. Also, you can display information about the status of the action in the main window using the method postMessage.
  4. When a user will visit the link they’ll see the logo of your integration, which you uploaded when you created it, it’s name and the list of the permissions which the application requires.
    We suggest that such pages should be opened as a modal window – in the popup. This will allow users to not lose the context of the page, which opened the popup.
  5. In case if a user is not authorized – it will be suggested to them to authorize in amoCRM, otherwise, the user will have a choice from accounts where they’re an administrator.
  6. After selecting an account and clicking on the button Allow, the integration will be installed in the selected account and the user will be redirected in modal or in the main window (based on a parameter of the mode) to Redirect URl, that you indicated on the setup of the integration stage with GET-parameters code, referrer, state, from_widget. Parameter code has Authorization code, parameter referrer – address of the account user, parameter state – string, that you sent when the window was opened, if string wasn’t sent, this parameter won’t return to you. If we send a webhook after installing the widget, as an addition you’ll receive GET-parameter from_widget.
  7. In case if the user will click on the button “Deny application in access”, he will be redirected to Redirect URl with GET-parameter error=access_denied, and with GET-parameter state, if it was sent before.

Example of processing authorization, if a parameter post_message was sent

With sent GET-parameter mode with value post_message in the window to allow access – the redirect will happen in the same window. Below we will discuss examples of interaction between a modal window to allow access and main window using function postMessage.

The code below is from the main window:

<script>
  var popup;

  auth();
  // 1. Opens window for allow access
  function auth(){
    popup = window.open('https://www.amocrm.com/oauth?client_id=XXX&state=XXX&mode=post_message', 'Allow access', 'scrollbars, status, resizable, width=750, height=580');
  }

  // 2. Registration of messages handler from popup window
  window.addEventListener('message',  updateAuthInfo);

  // 3. Handler function, registered above
  function  updateAuthInfo(e){
    if (e.data.error !== undefined) {
      console.log('Error -' + e.data.error)
    } else {
      console.log('Authorization is complete')
    }

    // 4. Closing modal window
    popup.close();
  }
</script>

Code below will be sent to the modal window from your backend server when the user gets to Redirect URl

<!doctype html>
<html lang="en">
<head>
  <title>oAuth Postback</title>
  <script>
    //Passing data to the main window, set of data is up to you to define
    if(window.opener){
      window.opener.postMessage({'error': undefined, 'status': 'ok'}, "*");
    }
  </script>
</head>
</html>

After processing the code above, the main window will indicate the result.
We recommend closing the modal window automatically, how it was done in the example, this way users won’t get confused in windows.

3. Exchange of the Authorization Code to access token and refresh token

When you get an Authorization code, you need to make a request to a special method /oauth2/access_token, as explained below. As a reply, you’ll get a pair of Access and Refresh token and the time in seconds until the token will expire.
The access token is an analogy to the key of the session. It can be saved in the application and used for the request to API before the life-span of it will expire. The token must be accessible only to your application, that’s why we recommend not saving it in cookies of the browser, open configuration files and etc.
URL of the Method
Post /oauth2/access_token

Parameters

Parameter Description
client_id Integration ID
client_secret Secret of the integration
grant_type Type of authorization data (for Authorization code – authorization_code)
code Acquired code of authorization
redirect_uri Redirect URI indicated in the integration settings

Parameters of the reply

Parameter Description
token_type Token type (Bearer)
expires_in Time in seconds, which shows when the token will expire
access_token Access token
refresh_token Refresh token

Example of a request

{
  "client_id": "xxxx",
  "client_secret": "xxxx",
  "grant_type": "authorization_code",
  "code": "xxxxxxx",
  "redirect_uri": "https://test.test"
}

Example of a reply

{
  "token_type": "Bearer",
  "expires_in": 86400,
  "access_token": "xxxxxx",
  "refresh_token": "xxxxx"
}

Getting an access token with Authorization code via bash

curl https://subdomain.amocrm.com/oauth2/access_token -d \
'{"client_id":"xxx-xxx-xxx-xxx-xxx","client_secret":"xxxxxx","grant_type":"authorization_code","code":"xxxxxxxx","redirect_uri":"https://test.test/"}' \
-H 'Content-Type:application/json' \
-X POST

Getting an access token with Authorization code via PHP

<?php
$subdomain = 'test'; ///subdomain of the account in question
$link = 'https://' . $subdomain . '.amocrm.com/oauth2/access_token'; //Creating URL for request

/** Gathering data for request */
$data = [
	'client_id' => 'xxxx',
	'client_secret' => 'xxxx',
	'grant_type' => 'authorization_code',
	'code' => 'xxxxxx',
	'redirect_uri' => 'https://test.ru/',
];

/**
 * We need to initiate a request to the server.
 * Let’s use library with cURL.
 * You can also use cross platform cURL, if you don’t code on PHP.
 */
$curl = curl_init(); //Saving descriptor cURL
/** Installing required options for session cURL  */
curl_setopt($curl,CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl,CURLOPT_USERAGENT,'amoCRM-oAuth-client/1.0');
curl_setopt($curl,CURLOPT_URL, $link);
curl_setopt($curl,CURLOPT_HTTPHEADER,['Content-Type:application/json']);
curl_setopt($curl,CURLOPT_HEADER, false);
curl_setopt($curl,CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($curl,CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($curl,CURLOPT_SSL_VERIFYHOST, 2);
$out = curl_exec($curl); //Initiating request to API and saving reply to variable
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
/** Now we can process replies from the server. It’s an example, you can process this data however you want it to. */
$code = (int)$code;
$errors = [
	400 => 'Bad request',
	401 => 'Unauthorized',
	403 => 'Forbidden',
	404 => 'Not found',
	500 => 'Internal server error',
	502 => 'Bad gateway',
	503 => 'Service unavailable',
];

try
{
	/** If the reply code is not successful - return an error message  */
	if ($code < 200 && $code > 204) {
		throw new Exception(isset($errors[$code]) ? $errors[$code] : 'Undefined error', $code);
	}
}
catch(\Exception $e)
{
	die('Error: ' . $e->getMessage() . PHP_EOL . 'Error code: ' . $e->getCode());
}

/**
 * Data will be received in JSON, that’s why to get readable data,
 * we need to parse that data that PHP will understand
 */
$response = json_decode($out, true);

$access_token = $response['access_token']; //Access token
$refresh_token = $response['refresh_token']; //Refresh token
$token_type = $response['token_type']; //Token type
$expires_in = $response['expires_in']; //In how much action of the token will expire

4. Getting a new access token once it expires

From the previous section you may have noticed that with an Access token we get a Refresh token. It is required to continue working with API, when the action of the Access token is expiring, it’s pretty common action.

Refresh token has two duration limitations:

  1. The refresh token lifespan is 3 months. If an integration is not used in 3 months, no request was made to actualize the key, then the integration will lose access to data and it’s required to ask for permission from the user again.
  2. The refresh token can be changed only once. After sending it to the method and getting a new pair access token/refresh token the old refresh token becomes not actual. After getting the new refresh token you need to save it, otherwise, you’ll need to ask for permissions from the user again.

When the action lifespan expires, the possibility of getting an Access token from Refresh becomes impossible. To exchange it it is required to make a request on the special method with the actual Refresh token. In reply, you will get a new Access and Refresh tokens.

URL of the method

POST /oauth2/access_token

Parameters

Parameter Description
client_id Integration ID
client_secret Secret of the integration
grant_type Type of authorization data (for refresh token – refresh_token)
refresh_token Refresh token
redirect_uri Redirect URI indicated in integration settings

Parameters of the reply

Parameter Description
token_type Type of token (Bearer)
expires_in Time in seconds, which shows in how much time the token will expire
access_token Access token
refresh_token Refresh token

Example of a request

{
  "client_id": "xxxx",
  "client_secret": "xxxx",
  "grant_type": "refresh_token",
  "refresh_token": "xxxxx",
  "redirect_uri": "https://test.test"
}

Example of a reply

{
  "token_type": "Bearer",
  "expires_in": 86400,
  "access_token": "xxxxxx",
  "refresh_token": "xxxxx"
}

Getting an Access token with Refresh token via bash

{
  "token_type": "Bearer",
  "expires_in": 86400,
  "access_token": "xxxxxx",
  "refresh_token": "xxxxx"
}

Getting an Access token with Authorization code via PHP

<?php
$subdomain = 'test'; //Subdomain of the account in question
$link = 'https://' . $subdomain . '.amocrm.com/oauth2/access_token'; //Creating URL for request

/** Gathering data for request */
$data = [
	'client_id' => 'xxxx',
	'client_secret' => 'xxxx',
	'grant_type' => 'authorization_code',
	'code' => 'xxxxxx',
	'redirect_uri' => 'https://test.ru/',
];

/**
 * We need to initiate the request to the server.
 * Let’s use the library with cURL.
 * You can also use cross-platform cURL if you don’t code on PHP.
 */
$curl = curl_init(); //Saving descriptor cURL
/** Installing required options for session cURL */
curl_setopt($curl,CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl,CURLOPT_USERAGENT,'amoCRM-oAuth-client/1.0');
curl_setopt($curl,CURLOPT_URL, $link);
curl_setopt($curl,CURLOPT_HTTPHEADER,['Content-Type:application/json']);
curl_setopt($curl,CURLOPT_HEADER, false);
curl_setopt($curl,CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($curl,CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($curl,CURLOPT_SSL_VERIFYHOST, 2);
$out = curl_exec($curl); //Initiating request to API and saving reply to variable
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
/** Now we can process replies from the server. It’s an example, you can process this data however you want it too. */
$code = (int)$code;
$errors = [
	400 => 'Bad request',
	401 => 'Unauthorized',
	403 => 'Forbidden',
	404 => 'Not found',
	500 => 'Internal server error',
	502 => 'Bad gateway',
	503 => 'Service unavailable',
];

try
{
	/** If code of the reply is not successful - return message of error */
	if ($code < 200 && $code > 204) {
		throw new Exception(isset($errors[$code]) ? $errors[$code] : 'Undefined error', $code);
	}
}
catch(\Exception $e)
{
	die('Error: ' . $e->getMessage() . PHP_EOL . 'Error code: ' . $e->getCode());
}

/**
 * Data will be received in JSON, that’s why to get readable data,
 * we need to parse data that PHP will understand
 */
$response = json_decode($out, true);

$access_token = $response['access_token']; //Access token
$refresh_token = $response['refresh_token']; //Refresh token
$token_type = $response['token_type']; //Type of token
$expires_in = $response['expires_in']; //In how much the action of the token will expire

5. Requests to API by exchanging an access token

With the help of acquired access token you can easily make requests to API of an application. For that you’ll need to make a bit of changes to the requests that are currently made to API.
You don’t need to send cookies-files with each request and you don’t need to authorize with parameters USER_LOGIN and USER_HASH, instead of that you need to add header Authorization: Bearer {access token}

Example of a request to method account

<?php
$subdomain = 'test'; //Subdomain of the account in question
$link = 'https://' . $subdomain . '.amocrm.com/api/v2/account'; //Creation of URL for request
/** Getting access_token from your storage */
$access_token = 'xxxx';
/** Creating headers */
$headers = [
	'Authorization: Bearer ' . $access_token
];
/**
 * We need to initiate a request to the server.
 * Let’s use library with cURL
 * You can also use cross platform cURL, if you don’t code on PHP.
 */
$curl = curl_init(); //Saving descriptor of cURL
/** Installing required options for session cURL  */
curl_setopt($curl,CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl,CURLOPT_USERAGENT,'amoCRM-oAuth-client/1.0');
curl_setopt($curl,CURLOPT_URL, $link);
curl_setopt($curl,CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl,CURLOPT_HEADER, false);
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($curl,CURLOPT_SSL_VERIFYHOST, 2);
$out = curl_exec($curl); //Initiating request to API and saving reply to variable
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
/** Now we can process replies from the server. It’s an example, you can process this data however you want to. */
$code = (int)$code;
$errors = [
	400 => 'Bad request',
	401 => 'Unauthorized',
	403 => 'Forbidden',
	404 => 'Not found',
	500 => 'Internal server error',
	502 => 'Bad gateway',
	503 => 'Service unavailable',
];

try
{
	/** If code of the reply is not successful - return message of error  */
	if ($code < 200 && $code > 204) {
		throw new Exception(isset($errors[$code]) ? $errors[$code] : 'Undefined error', $code);
	}
}
catch(\Exception $e)
{
	die(Error: ' . $e->getMessage() . PHP_EOL . 'Error code: ' . $e->getCode());
}

Like this, you can make requests to all methods of API, for which a token has enough permissions.

6. Errors handler

When working with the logic above,some exceptions that need to be handled may appear, let’s take a look at all of them:

  1. If a user didn’t give permission to access his account, in case you used the amoCRM button, the function will run, which will be sent in one of the parameters. You can read more in the article Button. Otherwise, if the page was opened without a button, in case of decline a redirect will happen on Redirect URI with GET-parameter error=access_denied.
  2. If the administrator of the account deactivated the installation of the integration, then given to the integration access_token will be sent back. When requesting API you will get HTTP code 401. To continue the work of an integration, an integrator needs to get authorization for their integration from the user.
  3. If you didn’t save the actual refresh token, it was lost or more than 3 months have passed, to continue the work of the integration, you need to go through the process of app authorization once again.
  4. If you lost the main keys of an integration or you published accidentally, then you can refresh the secret key in the modal window integration of the account, where it was created. After refreshing the secret key of the integration, you need to refresh the secret key in the configuration of your integrations.