License Management API
Overview
License Management API allows you to reallocate Grammarly licenses within your software asset management tool for better utilization and IT governance. You can programmatically access your subscription summary, list of users and their last activity dates, as well as automatically de-provision users according to custom criteria. For example, you may want to de-provision users who have been inactive for 90 days or more.
This developer guide explains how to get the subscription summary, get the list of users, remove users from the subscription, and more, to streamline and automate managing your Grammarly enterprise licenses. The API is intended for programmatic consumption. Organizations can access the API through an HTTP REST interface.
Get a list of users
GET https://api.grammarly.com/ecosystem/api/v1/users
This API endpoint retrieves a paginated list of users associated with a Grammarly institution. Each user object in the response includes the user ID, institution ID, email, name, admin identifier, and last activity timestamp.
Request Parameters
Parameter | Type | Required | Description |
---|---|---|---|
limit | Integer | No | Specifies the maximum number of user records to return per request. The minimum possible value is 1, while the maximum is 250. If the parameter is missing, it will default to 100. |
cursor | String | No | Specifies the starting point of the records to return, enabling pagination. When it’s not passed, the API will return the first set of users. The value in the returned next_cursor should be set to this cursor value to get the next page set. |
Example Request
An example cURL request to get the first ten users:
bash
curl -X GET \
'https://api.grammarly.com/ecosystem/api/v1/users?limit=10&cursor=XaB4' \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response Format
The response is a JSON object that includes an array of user objects and a paging
containing information about the data returned.
Response Parameters
Parameter | Type | Description |
---|---|---|
data | Array | An array of user objects containing user details (described below). |
paging | Object | An object containing info about the returned response (described below). |
Each user object in the data
array has the following structure:
Field | Type | Description |
---|---|---|
user_id | Integer | A unique identifier for the user. |
institution_id | Integer | The ID of the institution the user is associated with. |
email | String | The user’s email address. |
name | String | The full name of the user. |
last_activity_at | String | Timestamp of the user’s last recorded activity in ISO 8601 |
is_admin | Boolean | A boolean to identify if that user is an admin or not. Please note that we don’t support removing admin licenses at this time. |
The paging
object has the following structure:
Field | Type | Description |
---|---|---|
next_cursor | String | Set to the cursor that can be used to get the next set of users. It will not be available if no more data exists (reflected also in has_more below). |
cur_cursor | String | Set to the cursor passed in the request or not available if nothing existed. |
has_more | Boolean | Set to true if more data exists and can be requested. |
page_size | Integer | The total number of elements in the data array above. |
Example Response
An example response body:
json
{
"data": [
{
"user_id": 1234567890,
"institution_id": 6123456789,
"email": "john.doe@grammarly.com",
"name": "John Doe",
"last_activity_at": "2024-10-09T23:00:35.834Z",
"is_admin": true
},
{
"user_id": 1234567891,
"institution_id": 6123456789,
"email": "Jane.Doe@grammarly.com",
"name": "Jane Doe",
"last_activity_at": "2024-09-07T00:33:01.006Z",
"is_admin": false
}
],
"paging": {
"next_cursor": "MTYzNTc5NDQ1",
"cur_cursor": "OTIyNzQ3OTM=",
"has_more": true,
"page_size": 2
}
}
Usage Notes
Use limit
and cursor
parameters to manage pagination through the user list.
The last_activity_at
field helps track recent user engagement and is formatted in UTC. If the user had no activity at all, this field will be set to the time the user was created.
Remove the user from the institution
DELETE https://api.grammarly.com/ecosystem/api/v1/users/{userId}
This endpoint deletes a specified user from the Institution by their unique user ID.
Request Parameters
Parameter | Type | Required | Description |
---|---|---|---|
userId | Integer | Yes | The unique identifier of the user to delete. |
Example Request
An example cURL request to delete a user:
bash
curl -X DELETE \
'https://api.grammarly.com/ecosystem/api/v1/users/1234567890' \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response Format
A successful response typically contains a status code indicating the user was deleted. If the user was not found or the deletion failed, an error response is returned.
Successful Response (204 No Content)
If the deletion is successful, the server will return a 204 No Content
response, indicating that the user was deleted successfully and no content is returned in the body.
Error Responses
Status Code | Description |
---|---|
403 | Insufficient permissions to delete the user. |
404 | The user with the specified ID was not found. |
409 | The user is part of another institution and can’t be removed. |
500 | Server error during deletion. |
Get a list of invitees
GET https://api.grammarly.com/ecosystem/api/v1/invitees
This API endpoint retrieves a paginated list of invitees associated with a Grammarly institution. Each invitee object in the response includes the invitee ID, institution ID, email, name, admin identifier, status, and creation timestamp.
Request Parameters
Parameter | Type | Required | Description |
---|---|---|---|
limit | Integer | No | Specifies the maximum number of invitees' records to return per request. The minimum possible value is 1, while the maximum is 250. If the parameter is missing, it will default to 100. |
cursor | String | No | Specifies the starting point of the records to return, enabling pagination. When it’s not passed, the API will return the first set of invitees. The value in the returned next_cursor should be set to this cursor value to get the next page set. |
Example Request
An example cURL request to get the first ten invitees:
bash
curl -X GET \
'https://api.grammarly.com/ecosystem/api/v1/invitees?limit=10&cursor=XaB4' \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response Format
The response is a JSON object that includes an array of invitee objects and a paging
containing information about the data returned.
Response Parameters
Parameter | Type | Description |
---|---|---|
data | Array | An array of invitee objects containing invitee details (described below). |
paging | Object | An object containing information about the returned response (described below). |
Each invitee object in the data
array has the following structure:
Field | Type | Description |
---|---|---|
id | Integer | A unique identifier for the invitee. |
institution_id | Integer | The ID of the institution the invitee is associated with. |
email | String | The invitee’s email address. |
name | String | The full name of the invitee. |
created_at | String | Timestamp of the invitee’s creation time in ISO 8601. |
is_admin | Boolean | A boolean to identify if that invitee is an admin or not. |
status | String | Either INVITED or EXPIRED . The INVITED has a valid invite and can join the institution. The EXPIRED invitee has to be reinvited by the admin to be able to join and become a user. Note that an expired invitee still occupies a license until removed. |
The paging
object has the following structure:
Field | Type | Description |
---|---|---|
next_cursor | String | Set to the cursor that can be used to get the next set of invitees. It will not be available if no more data exists (reflected also in has_more below). |
cur_cursor | String | Set to the cursor passed in the request or not available if nothing existed. |
has_more | Boolean | Set to true if more data exists and can be requested. |
page_size | Integer | The total number of elements in the data array above. |
Example Response
An example response body:
json
{
"data": [
{
"id": 1234567890,
"institution_id": 6123456789,
"email": "john.doe@grammarly.com",
"name": "John Doe",
"created_at": "2023-05-16T18:19:36Z",
"status": "EXPIRED",
"is_admin": true
},
{
"id": 1234567891,
"institution_id": 6123456789,
"email": "Jane.Doe@grammarly.com",
"name": "Jane Doe",
"created_at": "2023-05-16T18:21:02Z",
"status": "INVITED",
"is_admin": false
}
],
"paging": {
"next_cursor": "MTYzNTc5NDQ1",
"cur_cursor": "OTIyNzQ3OTM=",
"has_more": true,
"page_size": 2
}
}
Usage Notes
Use limit
and cursor
parameters to manage pagination through the invitees list.
The created_at
field helps to identify when the invitee was invited and is formatted in UTC.
Remove the invitee from the institution
DELETE https://api.grammarly.com/ecosystem/api/v1/invitees/{inviteeId}
This endpoint deletes a specified invitee from the Institution by their unique invitee ID.
Request Parameters
Parameter | Type | Required | Description |
---|---|---|---|
inviteeId | Integer | Yes | The unique identifier of the invitee to delete. |
Example Request
An example cURL request to delete an invitee:
bash
curl -X DELETE \
'https://api.grammarly.com/ecosystem/api/v1/invitees/1234567890' \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response Format
A successful response typically contains a status code indicating the invitee was deleted. If the invitee was not found or the deletion failed, an error response is returned.
Successful Response (204 No Content)
If the deletion is successful, the server will return a 204 No Content
response, indicating that the invitee was deleted successfully and no content is returned in the body.
Error Responses
Status Code | Description |
---|---|
403 | Insufficient permissions to delete the user. |
404 | The invitee with the specified ID was not found. |
500 | Server error during deletion. |
Getting the institution summary
GET https://api.grammarly.com/ecosystem/api/v1/institutions-summary
This endpoint gets an overview of the institution.
Example Request
An example cURL request to get a summary for an institution:
bash
curl -X GET \
'https://api.grammarly.com/ecosystem/api/institutions-summary' \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response Format
The response is a JSON object that includes an object containing the requested info.
Response Parameters
Field | Type | Description |
---|---|---|
id | Integer | The institution ID. |
name | String | The name of the institution. |
seats | Integer | The total number of licenses in this subscription. |
enrolled | Integer | The number of users who joined your Grammarly institution. |
expiration_date | String | The expiration date of the subscription is in ISO 8601 date format. |
user_types | Object | An object specifying the types of current users (described below) |
The user_types
object has the following structure:
Field | Type | Description |
---|---|---|
admins | Integer | The number of admins in this institution. |
active | Integer | The number of active users in this institution, excluding admins. |
invited | Integer | The number of active or expired invitees. Removed invitees are omitted here. |
removed | Integer | The number of removed users and invitees (those users that were added and then removed for any reason, and invitees that were invited and then removed before accepting the invitation). |
overage_seats | Integer | It indicates the number of occupied seats that exceed those paid for in the subscription: admins + active + invited - seats . |
Example Response
An example response body:
json
{
"id": 6123456789,
"name": "Integration Business",
"seats": 15,
"enrolled": 4,
"expiration_date": "2023-05-03",
"user_types": {
"removed": 2,
"invited": 3,
"admins": 3,
"active": 1
}
}
Usage Notes
The parameters in the user_types
object will only be returned if they’re > 0.
Constraints
Max Request Rates
Consider exponential backoff to handle requests with status code 429. Load test results indicate an ideal base factor of 2 seconds.
50 requests per second. The maximum number of requests per endpoint.