curl --request POST \
--url https://api.tassyir.io/developer/cli/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=urn:ietf:params:oauth:grant-type:device_code \
--data 'device_code=<string>' \
--data client_id=tassyir-cliconst options = {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
device_code: '<string>',
client_id: 'tassyir-cli'
})
};
fetch('https://api.tassyir.io/developer/cli/token', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"access_token": "<string>",
"token_type": "Bearer",
"expires_in": 4503599627370496,
"scope": "developer",
"token_id": "<string>",
"user_id": "<string>",
"email": "<string>"
}{
"error": "access_denied",
"error_description": "<string>"
}{
"error": "invalid_request",
"error_description": "<string>"
}{
"error": "slow_down",
"error_description": "<string>"
}{
"statusCode": 123,
"message": "<string>",
"path": "<string>",
"requestId": "<string>"
}{
"statusCode": 123,
"message": "<string>",
"path": "<string>",
"requestId": "<string>"
}Poll for the developer token (RFC 8628 §3.4)
Every interval seconds: authorization_pending until the developer decides; slow_down (HTTP 400) when a poll comes too soon, after which the interval is 5 seconds longer (at most 60); stop on access_denied, expired_token or invalid_grant. A device code yields one token, once. 30 unknown device codes per IP a minute (429 slow_down).
Public: the CLI holds nothing yet.
curl --request POST \
--url https://api.tassyir.io/developer/cli/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=urn:ietf:params:oauth:grant-type:device_code \
--data 'device_code=<string>' \
--data client_id=tassyir-cliconst options = {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
device_code: '<string>',
client_id: 'tassyir-cli'
})
};
fetch('https://api.tassyir.io/developer/cli/token', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"access_token": "<string>",
"token_type": "Bearer",
"expires_in": 4503599627370496,
"scope": "developer",
"token_id": "<string>",
"user_id": "<string>",
"email": "<string>"
}{
"error": "access_denied",
"error_description": "<string>"
}{
"error": "invalid_request",
"error_description": "<string>"
}{
"error": "slow_down",
"error_description": "<string>"
}{
"statusCode": 123,
"message": "<string>",
"path": "<string>",
"requestId": "<string>"
}{
"statusCode": 123,
"message": "<string>",
"path": "<string>",
"requestId": "<string>"
}Body
Form-encoded (application/x-www-form-urlencoded, parsed flat) or a flat JSON object: at most 8 KB and 20 parameters, every value one string of at most 4,096 characters, a parameter sent twice refused (invalid_request).
"urn:ietf:params:oauth:grant-type:device_code"The device_code the first call answered.
4096^tsy_dc_The client starting the sign-in; another is invalid_client.
tassyir-cli Response
The developer token.
RFC 6749 §5.1: the developer token, once.
Send as Authorization: Bearer <access_token> to developer/* (nowhere else). Store it like a password.
^tsy_dt_[0-9A-Za-z]{43}$"Bearer"Seconds of idle expiry (90 days); every use extends it.
1 <= x <= 9007199254740991"developer"A Tassyir id: a string of digits.
^\d{1,20}$A Tassyir id: a string of digits.
^\d{1,20}$Who the CLI signed in as.