Jira & Confluence
Last updated
Was this helpful?
Last updated
Was this helpful?
Was this helpful?
[!NOTE|label:reference:]
[!NOTE]
X-Atlassian-Token
X-Force-Accept-Language
X-AAccountId
[!NOTE|label:references:]
$ curl -s https://jira.sample.com/rest/api/2/myself
# or via `user?username=<id>`
$ curl -s https://jira.sample.com/rest/api/2/user?username=marslo
get info
# get timezone
$ curl -s https://jira.sample.com/rest/api/2/mypreferences?key=jira.user.timezone
Asia/Shanghai
# get locale
$ curl --request GET \
--url 'https://jira.sample.com/rest/api/2/mypreferences/locale' \
--header 'Accept: application/json'
set info
# set timezone
$ curl --request PUT \
--url 'https://jira.sample.com/rest/api/2/mypreferences?key={key}' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '"<string>"'
# set local
$ curl --request PUT \
--url 'https://jira.sample.com/rest/api/2/mypreferences/locale' \
--user 'email@example.com:<api_token>' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{ "locale": "en_US" }'
$ curl -s \
-k \
-X GET https://${jiraName}/rest/api/2/issue/${jiraID} |
jq --raw-output
check attachment ID
$ curl -s \
-k \
-X GET https://${jiraName}/rest/api/2/issue/${jiraID}?fields=attachment |
jq --raw-output .fields.attachment[].id
get attachments download url
$ curl -s \
-k \
-X GET https://${jiraName}/rest/api/2/issue/${jiraID}?fields=attachment |
jq --raw-output .fields.attachment[].content
download all attachments in Jira
-I replace-str Replace occurrences of replace-str in the initial-arguments with names read from standard in- put. Also, unquoted blanks do not terminate input items; instead the separator is the new- line character. Implies -x and -L 1.
$ curl -s \
-k \
-X GET https://${jiraName}/rest/api/2/issue/${jiraID}?fields=attachment |
jq --raw-output .fields.attachment[].content |
xargs -I '{}' curl -sgOJL '{}'
$ curl -fsSL -XGET https://jira.sample.com/rest/api/2/project |
jq -r '.[] | [.key, .name] | join(" | ")' |
column -s '|' -t
[!TIP]
JQL pattern rule:
remove all space
%3D
instead of=
project=abc
->project%3Dabc
format JQL
[!TIP]
$ jql='project = abc AND issuetype = release order by updated desc'
$ jql=$(printf %s "${jql}" | jq -sRr @uri)
$ jql="$(sed 's/ //g;s/AND/ AND /g;s/OR/ OR /g;s/IN/ IN /g;s/IS/ IS /g' <<< "${jql}")"
$ jql="$(printf %s "${jql}" | jq -sRr @uri)"
# i.e.:
$ jql='project = abc AND issuetype = release'
$ jql="$(sed 's/ //g;s/AND/ AND /g;s/OR/ OR /g;s/IN/ IN /g;s/IS/ IS /g' <<< "${jql}")"
$ echo $jql
project=abc AND issuetype=release
$ jql="$(printf %s "${jql}" | jq -sRr @uri)"
$ echo $jql
project%3Dabc%20AND%20issuetype%3Drelease
api
[!NOTE]
:
maxResults
:integer
$ curl GET https://jira.sample.com/rest/api/2/user?key=JIRAUSER10100 |
jq -r
[!NOTE|label:references:]
[!NOTE]
to list all tokens for single user:
$ curl -v -XGET \ https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token/ | jq -r
to list tokens for all users:
$ curl -v \ -X GET \ https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/tokensByFilter | jq -r
$ curl -s -D- \
-XGET \
-H "Content-Type: application/json" \
https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token |
sed '/^\s*$/,$!d;//d' |
jq -r
get id, created, last access, and valid timestamp
or
[!TIP]
expiration keywords
tokenValidityTimeInMonths
[!NOTE|label:references:]
userFilter
valid user key
read above how to get a user key for a name or by email address; if you want to filter for more than one user, repeat that parameter for as many users you want to filter for
descriptionFilter
search term
string to search for in all token descriptions
notValidAfter
epoch Unix timestamp
tokens not valid anymore after that date/ time in milliseconds
tokenScope
integer
list token expired after certain time
$ curl "https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/tokensByFilter?notValidAfter=1688918956972" |
jq -r
# with limit and page
$ curl "https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/tokensByFilter?page=0&limit=1¬ValidAfter=1688918956972" |
jq -r
[!NOTE|label:references:]
$ openssl genrsa -out jira_privatekey.pem 1024
$ openssl req -newkey rsa:1024 -x509 -key jira_privatekey.pem -out jira_publickey.cer -days 365
$ openssl pkcs8 -topk8 -nocrypt -in jira_privatekey.pem -out jira_privatekey.pcks8
$ openssl x509 -pubkey -noout -in jira_publickey.cer > jira_publickey.pem
priority
[!NOTE|label:references:]
$ for _i in "blocker.png" "blocker.svg" "critical.png" "critical.svg" "high.png" "high.svg" "highest.png" "highest.svg" "low.png" "low.svg" "lowest.png" "lowest.svg" "major.png" "major.svg" "medium.png" "medium.svg" "minor.png" "minor.svg" "trivial.png" "trivial.svg"; do
echo "--> ${_i}"
curl -O https://jira-trigger-plugin.atlassian.net/images/icons/priorities/${_i}
done
$ confluenceName='confluence.domain.com'
$ pageID='143765713'
get page id:
$ curl -s https://${confluenceName}/rest/api/user/current | jq -r
$ curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq --raw-output
get space
$ curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq .space.key
get title
$ curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq .title
get page history
$ curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq .version.number
get next version
currentVer=$(curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq .version.number)
newVer=$((currentVer+1))
[!NOTE|label:references:]
$ url="https://${confluenceName}/rest/api/content/${pageID}"
$ page=$(curl -s ${url})
$ space=$(echo "${page}" | jq .space.key)
$ title=$(echo "${page}" | jq .title)
$ currentVer=$(echo "${page}" | jq .version.number)
$ newVer=$((currentVer+1))
$ cat > a.json << EOF
{
"id": "${pageID}",
"type": "page",
"title": ${title},
"space": {"key": ${space}},
"body": {
"storage": {
"value": "<h1>Hi confluence</h1>",
"representation": "storage"
}
},
"version": {"number":${newVer}}
}
EOF
$ curl -s \
-i \
-X PUT \
-H 'Content-Type: application/json' \
--data "$(cat a.json)" \
https://${confluenceName}/rest/api/content/${pageID}
result
create excerpt
include excerpt
result
insert svg image
[!TIP|label:get svg image:]
...
->Attachments
preview the image and get info from URL :
...&preview=/506105287/513281481/k8s-ha-cluster-stacked-etcd.v3.svg
edit source via
[!TIP|label:references:]
<p><ac:image ac:width="301"><ri:attachment ri:filename="SVG_logo.svg" /></ac:image></p>
[!NOTE|label:references:]
$ $ docker run -ti bobswiftapps/acli:latest acli -a getClientInfo
# or
$ docker run -ti bobswiftapps/acli:latest /bin/bash
bash-4.4# acli -a getClientInfo
# with env
$ cat .env
examplegear=jira -s https://examplegear.atlassian.net -u anonymous
examplegear_confluence=confluence -s https://examplegear.atlassian.net/wiki -u anonymous
$ docker run --env-file=.env -ti bobswiftapps/acli:latest /bin/bash
bash-5.0# acli $examplegear -a getServerInfo
# or
docker run -e examplegear='jira -s https://examplegear.atlassian.net -u anonymous' -ti bobswiftapps/acli:latest /bin/bash
bash-4.4# acli ${examplegear} -a getServerInfo
# with acli.properties
$ docker run -v ${PWD}/acli.properties:/opt/acli/acli.properties \
-ti bobswiftapps/acli:latest
# or prior to version 11.0.0, use:
$ docker run -v ${PWD}/acli.properties:/opt/atlassian-cli/acli.properties \
-ti bobswiftapps/acli:latest
# or with `ACLI_CONFIG` env
$ docker run -v ${PWD}/acli.properties:/tmp/acli.properties \
-e ACLI_CONFIG=/tmp/acli.properties \
-ti bobswiftapps/acli:latest \
acli -a getServerInfo --outputFormat 2
$ acli system setSecureProperty --name my.secret --secret -
Enter secure value: <secret value prompt>
Secure properties file does not yet exist. Creating...
Enter new secure properties password: <new password prompt>
Confirm secure properties password: <new password prompt>
Secure properties file created.
Value for key 'foo' set in secure properties file.
%20CONDITION%20
instead of CONDITION
AND
-> %20AND%20
OR
-> %20OR%20
startAt
: integer
validateQuery
: string
fields
: array<string>
expand
: string
properties
: array<string>
fieldsByKeys
: boolean
sample: search?jql=${jql}&maxResults=100&startAt=0
tokenExpirationDateTime
tokenExpirationDateTimeMillis
create new token with expiration time
[!NOTE|label:references:]
with
tokenValidityTimeInMonths
$ curl -v \ -d '{"tokenDescription":"<token-description>", "tokenValidityTimeInMonths" : 1}' \ -X POST \ --header "Content-Type: application/json" \ https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token
with
tokenExpirationDateTime
$ curl --silent \
--insecure \
--globoff \
--netrc-file ~/.netrc \
-XGET \
"https://jira.sample.com/rest/api/2/search?jql=${jql}" |
jq -r ${jqOpt}
# i.e.:
$ curlOpt='--silent --insecure --globoff --netrc-file ~/.netrc'
$ url='https://jira.sample.com/rest/api/2'
$ queryParams="startAt=0&maxResults=10"
$ jql='project = ABC AND issuetype = Release ORDER BY updated ASC' # copy from Jira website
$ jql="$(printf %s "${jql}" | jq -sRr @uri)"
$ curl "${curlOpt}" "${url}/search?jql=${jql}&${queryParams}" |
jq -r '.issues[]' |
jq -r '. | [.key, .fields.summary, .fields.status.name, .fields.issuetype.name, .fields.updated, .fields.created] | join("|")' |
while IFS='|' read -r _key _summary _status _issuetype _updated _created; do
echo "- [${_key}] - ${_summary}"
echo " - status : ${_status}"
echo " - issuetype : ${_issuetype}"
echo " - created : ${_created}"
echo " - updated : ${_updated}"
done
$ curl --silent \
--insecure \
--globoff \
--netrc-file ~/.netrc \
-XGET \
"https://jira.sample.com/rest/api/2/search?jql=${jql}" |
jq -r ${jqOpt}
# i.e.:
$ curlOpt='--silent --insecure --globoff --netrc-file ~/.netrc'
$ url='https://jira.sample.com/rest/api/2'
$ queryParams="startAt=0&maxResults=10"
$ jql='project = abc AND issuetype = release' # copy from Jira website
$ jql="$(sed 's/ //g;s/AND/ AND /g;s/OR/ OR /g;s/IN/ IN /g;s/IS/ IS /g' <<< "${jql}")"
$ jql="$(printf %s "${jql}" | jq -sRr @uri)"
$ curl "${curlOpt}" "${url}/search?jql=${jql}&${queryParams}" |
jq -r '.issues[]' |
jq -r '. | [.key, .fields.summary, .fields.status.name, .fields.issuetype.name, .fields.updated, .fields.created] | join("|")' |
while IFS='|' read -r _key _summary _status _issuetype _updated _created; do
echo "- [${_key}] - ${_summary}"
echo " - status : ${_status}"
echo " - issuetype : ${_issuetype}"
echo " - created : ${_created}"
echo " - updated : ${_updated}"
done
function epoch2timestamp() {
[[ 0 != $1 ]] && echo $(date -d @$(( $1/1000 )) +%FT%T.%3N%Z) || echo "0";
}
$ while read -r _id _created _lastAccess _validUntil; do
echo "${_id} $(epoch2timestamp ${_created}) $(epoch2timestamp ${_lastAccess}) $(epoch2timestamp ${_validUntil})";
done < <( curl -s -D- \
-XGET \
-H "Content-Type: application/json" \
https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token |
sed '/^\s*$/,$!d;//d' |
jq -r '.content[] | [ .id, .created, .lastAccessed, .validUntil ] | join( "\t" )'
) |
column -t
537 2024-01-31T21:32:51.000PST 2024-03-26T23:30:30.000PDT 2024-07-31T21:32:51.000PDT
579 2024-03-26T23:19:16.000PDT 0 2024-09-26T23:19:16.000PDT
# with header
$ ( echo "ID CREATED LASTACCESS VALIDUNTIL";
while read -r _id _created _lastAccess _validUntil; do
echo "${_id} $(epoch2timestamp ${_created}) $(epoch2timestamp ${_lastAccess}) $(epoch2timestamp ${_validUntil})";
done < <( curl -s -D- \
-XGET \
-H "Content-Type: application/json" \
https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token |
sed '/^\s*$/,$!d;//d' |
jq -r '.content[] | [ .id, .created, .lastAccessed, .validUntil ] | join( "\t" )'
)
) | column -t
ID CREATED LASTACCESS VALIDUNTIL
537 2024-01-31T21:32:51.000PST 2024-03-26T23:33:33.000PDT 2024-07-31T21:32:51.000PDT
579 2024-03-26T23:19:16.000PDT 0 2024-09-26T23:19:16.000PDT
$ curl -s -D- \
-XGET \
-H "Content-Type: application/json" \
https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token |
sed '/^\s*$/,$!d;//d' |
jq -r '.content[] | [ .created, .lastAccessed, .validUntil ] | join("\n")' |
xargs -r -I{} bash -c "et=\"{}\"; date -d @\$(( \${et}/1000 )) +%c"
Mon 18 Dec 2023 10:25:58 AM PST
Tue 26 Mar 2024 10:21:30 PM PDT
Tue 18 Jun 2024 10:25:58 AM PDT
# or
$ while read -r _d; do
date -d @$(( ${_d}/1000 )) +%c;
done < <( curl -s -D- \
-XGET \
-H "Content-Type: application/json" \
https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token |
sed '/^\s*$/,$!d;//d' |
jq -r '.content[] | [ .created, .lastAccessed, .validUntil ] | join("\n")'
)
Mon 18 Dec 2023 10:25:58 AM PST
Tue 26 Mar 2024 10:14:58 PM PDT
Tue 18 Jun 2024 10:25:58 AM PDT
$ curl -v \
-d '{"tokenDescription":"Updated token description"}' \
-X PATCH \
--header "Content-Type: application/json" \
https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token/<token-id>
$ curl -v \
-X DELETE \
https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token/<token-id>
# list before token deleted
$ ( echo "ID CREATED LASTACCESS VALIDUNTIL";
while read -r _id _created _lastAccess _validUntil; do
echo "${_id} $(epoch2timestamp ${_created}) $(epoch2timestamp ${_lastAccess}) $(epoch2timestamp ${_validUntil})";
done < <( curl -s -D- \
-XGET \
-H "Content-Type: application/json" \
https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token |
sed '/^\s*$/,$!d;//d' |
jq -r '.content[] | [ .id, .created, .lastAccessed, .validUntil ] | join( "\t" )'
)
) | column -t
ID CREATED LASTACCESS VALIDUNTIL
537 2024-01-31T21:32:51.000PST 2024-03-26T23:40:02.000PDT 2024-07-31T21:32:51.000PDT
579 2024-03-26T23:19:16.000PDT 0 2024-09-26T23:19:16.000PDT
580 2024-03-26T23:36:02.000PDT 0 2024-09-26T23:36:02.000PDT
581 2024-03-26T23:36:11.000PDT 0 2024-09-26T23:36:11.000PDT
# delete
$ curl -s -D- \
-X DELETE \
https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token/581
HTTP/2 200
date: Wed, 27 Mar 2024 06:41:06 GMT
content-type: application/json;charset=UTF-8
x-arequestid: 1421x248002x2
x-anodeid: jiraprod5
referrer-policy: strict-origin-when-cross-origin
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
content-security-policy: sandbox
strict-transport-security: max-age=31536000
set-cookie: JSESSIONID=731380C1F17B2F9A59E211B0442AAFFB; Path=/; Secure; HttpOnly
x-seraph-loginreason: OK
set-cookie: atlassian.xsrf.token=A8KN-1NAU-M55V-EQSR_1811ae8601112c05430589e686032924599718c9_lin; Path=/; Secure; SameSite=None
x-asessionid: k5q153
x-ausername: marslo
cache-control: no-cache, no-store, no-transform
true
# curl without header
$ curl -s \
-X DELETE \
https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token/580
true
# verify
$ ( echo "ID CREATED LASTACCESS VALIDUNTIL";
while read -r _id _created _lastAccess _validUntil; do
echo "${_id} $(epoch2timestamp ${_created}) $(epoch2timestamp ${_lastAccess}) $(epoch2timestamp ${_validUntil})";
done < <( curl -s -D- \
-XGET \
-H "Content-Type: application/json" \
https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token |
sed '/^\s*$/,$!d;//d' |
jq -r '.content[] | [ .id, .created, .lastAccessed, .validUntil ] | join( "\t" )'
)
) | column -t
ID CREATED LASTACCESS VALIDUNTIL
537 2024-01-31T21:32:51.000PST 2024-03-26T23:44:32.000PDT 2024-07-31T21:32:51.000PDT
579 2024-03-26T23:19:16.000PDT 0 2024-09-26T23:19:16.000PDT
$ curl GET \
https://jira.sample.com/rest/api/2/user?username=some.username |
jq -r
0 = no scope (all pre 1.5.0 tokens), 1 = read-only, 2 = read/ write
fromCreated
epoch Unix timestamp
-
untilCreated
epoch Unix timestamp
-
fromLastUsed
epoch Unix timestamp
-
untilLastUsed
epoch Unix timestamp
-
fromExpiresDuring
epoch Unix timestamp
-
untilExpiresDuring
epoch Unix timestamp
-
<img width="800" src="https://ewiki.sample.com/download/attachments/506105287/513281481/k8s-ha-cluster-stacked-etcd.v3.svg">
$ curl -v -d '{"tokenDescription":"<token-description>"}' \
-X POST \
--header "Content-Type: application/json" \
https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token
$ curl -v \
-d '{"tokenDescription":"Custom expiration", "tokenExpirationDateTime" : "2020-10-19T10:29:00.000+02:00"}' \
-X POST \
--header "Content-Type: application/json" \
https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token
$ curl -s \
-d '{"tokenDescription":"marslo-token-api-test", "tokenValidityTimeInMonths" : 6}' \
-X POST \
--header "Content-Type: application/json" \
https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token |
jq -r .plainTextToken
NdxEToKfDsjUE7tct1ePP6erE1xdDsEAa64BOT
$ curl -v \
-d '{"tokenDescription":"token for another user", "tokenForUserKey":"JIRAUSER10105"}' \
POST \
--header "Content-Type: application/json" \
https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token
# or with token validity time
$ curl -v \
-d '{"tokenDescription":"token for another user", "tokenForUserKey":"JIRAUSER10105","tokenValidityTimeInMonths":12}' \
POST \
--header "Content-Type: application/json" \
https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token