GitLab Subscriptions Internal API
The GitLab Subscriptions internal API is used by the CustomersDot application, it cannot be used by other consumers. This documentation is intended for people working on the GitLab and CustomersDot codebases.
Add new endpoints
API endpoints should be externally accessible by default, with proper authentication and authorization. Before adding a new internal endpoint, consider if the API would benefit the wider GitLab community and can be made externally accessible.
For the GitLab Subscription portal, we might chose to use an internal API when we need to make updates to GitLab without the context of a user. This means we don't have access to a user's access token, and instead make updates as the CustomersDot application in general.
Authentication
CustomersDot JWT
These endpoints are all authenticated using JWT authentication from CustomersDot.
To authenticate using the JWT, clients:
- Read the contents of the signing key from the credentials.
- Use the signing key to generate a JSON Web Token (
JWT
). - Pass the JWT in the
X-CUSTOMERS-DOT-INTERNAL-TOKEN
header.
Admin personal access token (PAT)
This authentication method is deprecated as it is not supported in the Cells architecture. It will be removed in a future milestone. Please use JWT authentication instead.
To authenticate as an administrator, generate a personal access token for an administrator with the
api
and admin_mode
scopes. This token can then be supplied in the PRIVATE-TOKEN
header.
Internal Endpoints
Namespaces
Fetch group owners
Use a GET command to get direct owners of the namespace. CustomersDot uses this endpoint to find users to notify about billing events.
GET /internal/gitlab_subscriptions/namespaces/:id/owners
Example request:
curl --header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>" "https://gitlab.com/api/v4/internal/gitlab_subscriptions/namespaces/1234/owners"
Example response:
[
{
"user": {
"id": 1,
"username": "john_smith",
"name": "John Smith"
},
"access_level": 50,
"notification_email": "name@example.com"
}
]
Fetch a namespace by ID
Used to fetch information about a namespace.
GET /internal/gitlab_subscriptions/namespaces/:id
Parameters:
Attribute | Type | Required | Description |
---|---|---|---|
id |
integer/string | yes | ID or URL-encoded path of the namespace |
Example request:
curl --request GET --header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>" "https://gitlab.com/api/v4/internal/gitlab_subscriptions/namespaces/1"
Example response:
{
"id": 1,
"name": "group1",
"path": "group1",
"kind": "group",
"full_path": "group1",
"parent_id": null,
"avatar_url": null,
"web_url": "https://gitlab.example.com/groups/group1",
"members_count_with_descendants": 2,
"billable_members_count": 2,
"max_seats_used": 0,
"seats_in_use": 0,
"plan": "default",
"end_date": null,
"trial_ends_on": null,
"trial": false,
"root_repository_size": 100,
"projects_count": 3
}
Update a namespace
Use a PUT command to update an existing namespace.
PUT /internal/gitlab_subscriptions/namespaces/:id
Parameters:
Attribute | Type | Required | Description |
---|---|---|---|
id |
integer/string | yes | ID or URL-encoded path of the namespace |
shared_runners_minutes_limit |
integer | no | Compute minutes quota |
extra_shared_runners_minutes_limit |
integer | no | Extra compute minutes |
additional_purchased_storage_size |
integer | no | Additional storage size |
additional_purchased_storage_ends_on |
date | no | Additional purchased storage Ends on |
gitlab_subscription_attributes |
hash | no | Hash object containing GitLab Subscription attributes. Accepts seats ,max_seats_used ,plan_code ,end_date ,auto_renew ,trial ,trial_ends_on ,trial_starts_on ,trial_extension_type
|
Example request:
curl --request PUT --header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>" "https://gitlab.com/api/v4/internal/gitlab_subscriptions/namespaces/1 --data '{"shared_runners_minutes_limit":1000}'"
Example response:
{
"id": 1,
"name": "group1",
"path": "group1",
"kind": "group",
"full_path": "group1",
"parent_id": null,
"avatar_url": null,
"web_url": "https://gitlab.example.com/groups/group1",
"members_count_with_descendants": 2,
"billable_members_count": 2,
"max_seats_used": 0,
"seats_in_use": 0,
"plan": "default",
"end_date": null,
"trial_ends_on": null,
"trial": false,
"root_repository_size": 100,
"projects_count": 3
}
Subscriptions
The subscription endpoints are used by
CustomersDot (customers.gitlab.com
) to
apply subscriptions (including trials, and add-on purchases) to personal namespaces, or top-level
groups on GitLab.com.
Fetch a subscription
Use a GET command to view an existing subscription.
GET /internal/gitlab_subscriptions/namespaces/:id/gitlab_subscription
Example request:
curl --header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>" "https://gitlab.com/api/v4/internal/gitlab_subscriptions/namespaces/1234/gitlab_subscription"
Example response:
{
"plan": {
"code": "premium",
"name": "premium",
"trial": false,
"auto_renew": null,
"upgradable": false,
"exclude_guests": false
},
"usage": {
"seats_in_subscription": 80,
"seats_in_use": 82,
"max_seats_used": 82,
"seats_owed": 2
},
"billing": {
"subscription_start_date": "2020-07-15",
"subscription_end_date": "2021-07-15",
"trial_ends_on": null
}
}
Upcoming Reconciliations
The upcoming_reconciliations
endpoint is used by CustomersDot (customers.gitlab.com
)
to update upcoming reconciliations for namespaces.
Update an upcoming reconciliation
PUT /internal/gitlab_subscriptions/namespaces/:namespace_id/upcoming_reconciliations
Attribute | Type | Required | Description |
---|---|---|---|
namespace_id |
ID | yes | ID of the namespace with the upcoming reconciliation |
next_reconciliation_date |
date | yes | Date the reconciliation will occur on |
display_alert_from |
date | yes | Date to start display the upcoming reconciliation alert |
Example request:
curl --request PUT --header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>" --header "Content-Type: application/json" \
--data '{"upcoming_reconciliations": [{"next_reconciliation_date": "12 Jun 2021", "display_alert_from": "05 Jun 2021"}]}' \
"https://gitlab.com/api/v4/internal/gitlab_subscriptions/129/upcoming_reconciliations"
Example response:
200
Delete an upcoming reconciliation
Use a DELETE command to delete an upcoming_reconciliation
.
DELETE /internal/gitlab_subscriptions/namespaces/:namespace_id/upcoming_reconciliations
Example request:
curl --request DELETE \
--url "http://localhost:3000/api/v4/internal/gitlab_subscriptions/namespaces/22/upcoming_reconciliations" \
--header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>"
Example response:
204
Users
Retrieve a user
Use a GET command to get the User object based on user ID.
GET /internal/gitlab_subscriptions/users/:id
Example request:
curl --header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>" "https://gitlab.com/api/v4/internal/gitlab_subscriptions/users/:id"
Example response:
{
"id": 1,
"username": "john_smith",
"name": "John Smith",
"web_url": "http://localhost:3000/john_smith"
}
Fetch user permissions in a namespace
Use a GET command to fetch the permissions a user has in a namespace.
GET /internal/gitlab_subscriptions/namespaces/:namespace_id/user_permissions/:user_id
Example request:
curl --header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>" "https://gitlab.com/api/v4/internal/gitlab_subscriptions/namespaces/:namespace_id/user_permissions/:user_id"
Example response:
{
"edit_billing": true
}
Update credit card validation
Use a PUT command to update the User's credit card validation
PUT /internal/gitlab_subscriptions/users/:user_id/credit_card_validation
Example request:
curl --request PUT --header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>" \
--data '{"credit_card_validated_at": "2020-01-01 00:00:00 UTC", "credit_card_expiration_year": "2010", "credit_card_expiration_month": "12", "credit_card_holder_name": "John Smith", "credit_card_type": "American Express", "credit_card_mask_number": "1111", "zuora_payment_method_xid": "abc123", "stripe_setup_intent_xid": "seti_abc123", "stripe_payment_method_xid": "pm_abc123", "stripe_card_fingerprint": "card123"}' \
"https://gitlab.com/api/v4/internal/gitlab_subscriptions/users/:user_id/credit_card_validation"
Example response:
{
"success": {}
}
Migrating Endpoints
These endpoints are going to be migrated to internal endpoints. After that, they will be deprecated and then removed in a future milestone.
Add-On Purchases
This API is used by CustomersDot to manage add-on purchases, excluding Compute Minutes and Storage packs.
Create multiple subscription add-on purchases (Internal)
Use a POST command to create, update, and deprovision multiple subscription add-on purchases. Possible add-on types are duo_pro
, duo_enterprise
, and product_analytics
.
POST /namespaces/:id/subscription_add_on_purchase
Supported attributes:
Attribute | Type | Required | Description |
---|---|---|---|
quantity |
integer | No | Amount of units in the subscription add-on purchase. Must be a non-negative integer. (Example: Number of seats for Duo Pro add-on) |
started_on |
date | Yes | Date the subscription add-on purchase became available |
expires_on |
date | Yes | Expiration date of the subscription add-on purchase |
purchase_xid |
string | No | Identifier for the subscription add-on purchase (Example: Subscription name for a Code Suggestions add-on) |
trial |
boolean | No | Whether the add-on is a trial |
If successful, returns 201
and the following response attributes:
Attribute | Type | Description |
---|---|---|
namespace_id |
integer | Unique identifier for the namespace associated with the purchase |
namespace_name |
string | Name of the namespace linked to the purchase |
add_on |
integer | Type of add-on related to the purchase. Possible add-on types are Code Suggestions alias Duo Pro, Duo Enterprise and Product Analytics
|
quantity |
integer | Number of units purchased for the subscription add-on |
started_on |
date | Date the subscription add-on became active |
expires_on |
date | Date the subscription add-on will expire |
purchase_xid |
string | Unique identifier for the subscription add-on purchase |
trial |
boolean | Indicates whether the add-on is part of a trial |
Example request for create/update:
curl --request POST \
--header --header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>" \
--header "Content-Type: application/json" \
--data '{ "add_on_purchases": { "duo_pro": [{ "quantity": 1, "started_on": "<YYYY-MM-DD>", "expires_on": "<YYYY-MM-DD>", "purchase_xid": "A-S0000001", "trial": false }] } }' \
"https://gitlab.com/api/v4/internal/gitlab_subscriptions/namespaces/1234/subscription_add_on_purchases"
Example request for deprovision:
curl --request POST \
--header --header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>" \
--header "Content-Type: application/json" \
--data '{ "add_on_purchases": { "duo_pro": [{ "started_on": "<YYYY-MM-DD>", "expires_on": "<YYYY-MM-DD>" }] } }' \
"https://gitlab.com/api/v4/internal/gitlab_subscriptions/namespaces/1234/subscription_add_on_purchases"
The dates should reflect the day prior to the request, i.e., yesterday.
Example response:
[
{
"namespace_id": 1234,
"namespace_name": "namespace-name",
"add_on": "Code Suggestions",
"quantity": 1,
"started_on": "2024-01-01",
"expires_on": "2024-12-31",
"purchase_xid": "A-S0000001",
"trial": false
}
]
Create a subscription add-on purchase
Use a POST command to create a subscription add-on purchase.
POST /namespaces/:id/subscription_add_on_purchase/:add_on_name
Attribute | Type | Required | Description |
---|---|---|---|
quantity |
integer | yes | Amount of units in the subscription add-on purchase (Example: Number of seats for a Code Suggestions add-on) |
started_on |
date | yes | Date the subscription add-on purchase became available |
expires_on |
date | yes | Expiration date of the subscription add-on purchase |
purchase_xid |
string | yes | Identifier for the subscription add-on purchase (Example: Subscription name for a Code Suggestions add-on) |
trial |
boolean | no | Whether the add-on is a trial |
Example request:
curl --request POST --header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>" "https://gitlab.com/api/v4/namespaces/1234/subscription_add_on_purchase/code_suggestions?&quantity=10&started_on="2024-06-15"&expires_on="2024-07-15"&purchase_xid="A-S12345678"&trial=true"
Example response:
{
"namespace_id":1234,
"namespace_name":"A Namespace Name",
"add_on":"Code Suggestions",
"quantity":10,
"started_on":"2024-06-15",
"expires_on":"2024-07-15",
"purchase_xid":"A-S12345678",
"trial":true
}
Update a subscription add-on purchase
Use a PUT command to update an existing subscription add-on purchase.
PUT /namespaces/:id/subscription_add_on_purchase/:add_on_name
Attribute | Type | Required | Description |
---|---|---|---|
quantity |
integer | no | Amount of units in the subscription add-on purchase (Example: Number of seats for a Code Suggestions add-on) |
started_on |
date | yes | Date the subscription add-on purchase became available |
expires_on |
date | yes | Expiration date of the subscription add-on purchase |
purchase_xid |
string | no | Identifier for the subscription add-on purchase (Example: Subscription name for a Code Suggestions add-on) |
trial |
boolean | no | Whether the add-on is a trial |
Example request:
curl --request PUT --header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>" "https://gitlab.com/api/v4/namespaces/1234/subscription_add_on_purchase/code_suggestions?&quantity=15&started_on="2024-06-15"&expires_on="2024-07-15"&purchase_xid="A-S12345678"&trial=true"
Example response:
{
"namespace_id":1234,
"namespace_name":"A Namespace Name",
"add_on":"Code Suggestions",
"quantity":15,
"started_on":"2024-06-15",
"expires_on":"2024-07-15",
"purchase_xid":"A-S12345678",
"trial":true
}
Fetch a subscription add-on purchases
Use a GET command to view an existing subscription add-on purchase.
GET /namespaces/:id/subscription_add_on_purchase/:add_on_name
Example request:
curl --header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>" "https://gitlab.com/api/v4/namespaces/1234/subscription_add_on_purchase/code_suggestions"
Example response:
{
"namespace_id":1234,
"namespace_name":"A Namespace Name",
"add_on":"Code Suggestions",
"quantity":15,
"started_on":"2024-06-15",
"expires_on":"2024-07-15",
"purchase_xid":"A-S12345678",
"trial":true
}
Compute quota provisioning
- Renamed from "CI/CD minutes" to "compute quota" and "compute minutes" in GitLab 16.1.
The compute quota endpoints are used by CustomersDot (customers.gitlab.com
)
to apply additional packs of compute minutes, for personal namespaces or top-level groups in GitLab.com.
Create an additional pack
Use a POST command to create additional packs.
POST /namespaces/:id/minutes
Attribute | Type | Required | Description |
---|---|---|---|
packs |
array | yes | An array of purchased compute packs |
packs[expires_at] |
date | yes | Expiry date of the purchased pack |
packs[number_of_minutes] |
integer | yes | Number of additional compute minutes |
packs[purchase_xid] |
string | yes | The unique ID of the purchase |
Example request:
curl --request POST \
--url "http://localhost:3000/api/v4/namespaces/123/minutes" \
--header 'Content-Type: application/json' \
--header 'X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>' \
--data '{
"packs": [
{
"number_of_minutes": 10000,
"expires_at": "2022-01-01",
"purchase_xid": "46952fe69bebc1a4de10b2b4ff439d0c"
}
]
}'
Example response:
[
{
"namespace_id": 123,
"expires_at": "2022-01-01",
"number_of_minutes": 10000,
"purchase_xid": "46952fe69bebc1a4de10b2b4ff439d0c"
}
]
Move additional packs
Use a PATCH
command to move additional packs from one namespace to another.
PATCH /namespaces/:id/minutes/move/:target_id
Attribute | Type | Required | Description |
---|---|---|---|
id |
string | yes | The ID of the namespace to transfer packs from |
target_id |
string | yes | The ID of the target namespace to transfer the packs to |
Example request:
curl --request PATCH \
--url "http://localhost:3000/api/v4/namespaces/123/minutes/move/321" \
--header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>"
Example response:
{
"message": "202 Accepted"
}
Subscriptions (being migrated)
The subscription endpoints are used by
CustomersDot (customers.gitlab.com
) to
apply subscriptions (including trials) to personal namespaces, or top-level groups on GitLab.com.
Create a subscription
Use a POST command to create a subscription.
POST /namespaces/:id/gitlab_subscription
Attribute | Type | Required | Description |
---|---|---|---|
start_date |
date | yes | Start date of subscription |
end_date |
date | no | End date of subscription |
plan_code |
string | no | Subscription tier code |
seats |
integer | no | Number of seats in subscription |
max_seats_used |
integer | no | Highest number of active users in the last month |
auto_renew |
boolean | no | Whether subscription auto-renews on end date |
trial |
boolean | no | Whether subscription is a trial |
trial_starts_on |
date | no | Start date of trial |
trial_ends_on |
date | no | End date of trial |
Example request:
curl --request POST --header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>" "https://gitlab.com/api/v4/namespaces/1234/gitlab_subscription?start_date="2020-07-15"&plan="premium"&seats=10"
Example response:
{
"plan": {
"code":"premium",
"name":"premium",
"trial":false,
"auto_renew":null,
"upgradable":false
},
"usage": {
"seats_in_subscription":10,
"seats_in_use":1,
"max_seats_used":0,
"seats_owed":0
},
"billing": {
"subscription_start_date":"2020-07-15",
"subscription_end_date":null,
"trial_ends_on":null
}
}
Update a subscription
Use a PUT command to update an existing subscription.
PUT /namespaces/:id/gitlab_subscription
Attribute | Type | Required | Description |
---|---|---|---|
start_date |
date | no | Start date of subscription |
end_date |
date | no | End date of subscription |
plan_code |
string | no | Subscription tier code |
seats |
integer | no | Number of seats in subscription |
max_seats_used |
integer | no | Highest number of active users in the last month |
auto_renew |
boolean | no | Whether subscription auto-renews on end date |
trial |
boolean | no | Whether subscription is a trial |
trial_starts_on |
date | no | Start date of trial. Required if trial is true. |
trial_ends_on |
date | no | End date of trial |
Example request:
curl --request PUT --header "X-CUSTOMERS-DOT-INTERNAL-TOKEN: <json-web-token>" "https://gitlab.com/api/v4/namespaces/1234/gitlab_subscription?max_seats_used=0"
Example response:
{
"plan": {
"code":"premium",
"name":"premium",
"trial":false,
"auto_renew":null,
"upgradable":false
},
"usage": {
"seats_in_subscription":80,
"seats_in_use":82,
"max_seats_used":0,
"seats_owed":2
},
"billing": {
"subscription_start_date":"2020-07-15",
"subscription_end_date":"2021-07-15",
"trial_ends_on":null
}
}
Deprecated Endpoints
These endpoints are no longer being used by CustomersDot as an internal version of these endpoints has already been created. They will be removed in a future milestone.
Subscriptions (deprecated)
These endpoints have been replaced with the ones in the Internal Subscriptions API.
Fetch a subscription (namespaces API)
Use a GET command to view an existing subscription.
GET /namespaces/:id/gitlab_subscription
Example request:
curl --header "TOKEN: <admin_access_token>" "https://gitlab.com/api/v4/namespaces/1234/gitlab_subscription"
Example response:
{
"plan": {
"code":"premium",
"name":"premium",
"trial":false,
"auto_renew":null,
"upgradable":false,
"exclude_guests":false
},
"usage": {
"seats_in_subscription":80,
"seats_in_use":82,
"max_seats_used":82,
"seats_owed":2
},
"billing": {
"subscription_start_date":"2020-07-15",
"subscription_end_date":"2021-07-15",
"trial_ends_on":null
}
}