Creating credentials via Jenkins API

Jenkins setup:

Jenkins: 2.492.2
OS: Linux - 6.14.0-1009-aws
Java: 17.0.15 - Ubuntu (OpenJDK 64-Bit Server VM)
---
Office-365-Connector:5.1.0
allure-jenkins-plugin:2.32.0
apache-httpcomponents-client-4-api:4.5.14-269.vfa_2321039a_83
asm-api:9.7.1-97.v4cc844130d97
bootstrap5-api:5.3.3-2
bouncycastle-api:2.30.1.80-256.vf98926042a_9b_
branch-api:2.1214.v3f652804588d
browserstack-integration:1.2.16
caffeine-api:3.2.0-161.v691ef352cee1
checks-api:367.v18b_7f530e54a_
cloudbees-folder:6.991.v1d5f531726d0
commons-lang3-api:3.17.0-84.vb_b_938040b_078
commons-text-api:1.13.0-153.v91dcd89e2a_22
config-file-provider:982.vb_a_e458a_37021
copyartifact:765.v0357cc6e6eb_3
cors-filter:21.v34a_0a_7179a_5a_
credentials:1415.v831096eb_5534
credentials-binding:702.vfe613e537e88
display-url-api:2.209.v582ed814ff2f
durable-task:587.v84b_877235b_45
echarts-api:5.6.0-2
eddsa-api:0.3.0.1-19.vc432d923e5ee
font-awesome-api:6.7.2-1
git:5.7.0
git-client:6.1.2
github:1.42.0
github-api:1.321-478.vc9ce627ce001
gson-api:2.12.1-113.v347686d6729f
instance-identity:203.v15e81a_1b_7a_38
ionicons-api:82.v0597178874e1
jackson2-api:2.18.3-402.v74c4eb_f122b_2
jakarta-activation-api:2.1.3-2
jakarta-mail-api:2.1.3-2
javadoc:327.vdfe586651ee0
javax-activation-api:1.2.0-8
javax-mail-api:1.6.2-11
jaxb:2.3.9-133.vb_ec76a_73f706
job-dsl:1.91
joda-time-api:2.14.0-127.v7d9da_295a_d51
jquery:1.12.4-3
jquery3-api:3.7.1-3
jsch:0.2.16-95.v3eecb_55fa_b_78
json-api:20250107-125.v28b_a_ffa_eb_f01
json-path-api:2.9.0-148.v22a_7ffe323ce
junit:1319.v000471ca_e5e2
mailer:489.vd4b_25144138f
matrix-project:847.v88a_f90ff9f20
maven-plugin:3.25
mina-sshd-api-common:2.14.0-143.v2b_362fc39576
mina-sshd-api-core:2.14.0-143.v2b_362fc39576
nested-view:1.36
nodejs:1.6.4
okhttp-api:4.11.0-183.va_87fc7a_89810
oss-symbols-api:324.v432cce4172ca_
parameterized-trigger:859.vb_e3907a_07a_16
pipeline-build-step:567.vea_ce550ece97
pipeline-github-lib:65.v203688e7727e
pipeline-groovy-lib:752.vdddedf804e72
pipeline-input-step:527.vd61b_1d3c5078
pipeline-milestone-step:138.v78ca_76831a_43
pipeline-model-api:2.2255.v56a_15e805f12
pipeline-model-definition:2.2255.v56a_15e805f12
pipeline-model-extensions:2.2255.v56a_15e805f12
pipeline-stage-step:322.vecffa_99f371c
pipeline-stage-tags-metadata:2.2255.v56a_15e805f12
plain-credentials:199.v9f8e1f741799
plugin-util-api:6.1.0
postbuild-task:72.v75dc459e4747
resource-disposer:0.25
scm-api:704.v3ce5c542825a_
script-security:1373.vb_b_4a_a_c26fa_00
snakeyaml-api:2.3-123.v13484c65210a_
ssh-credentials:359.v2191c4cf635f
sshd:3.353.v2b_d33c46e970
structs:350.v3b_30f09f2363
token-macro:444.v52de7e9c573d
trilead-api:2.209.v0e69b_c43c245
variant:70.va_d9f17f859e0
workflow-aggregator:608.v67378e9d3db_1
workflow-api:1366.vf1fb_e1a_f6b_22
workflow-basic-steps:1079.vce64b_a_929c5a_
workflow-cps:4046.v90b_1b_9edec67
workflow-durable-task-step:1405.v1fcd4a_d00096
workflow-job:1506.v77f78a_b_8cc5e
workflow-multibranch:806.vb_b_688f609ee9
workflow-scm-step:437.v05a_f66b_e5ef8
workflow-step-api:704.ve4f0967e98fa_
workflow-support:963.va_600813d04a_a_
ws-cleanup:0.48
xray-connector:2.6.1

Hello! Could anyone please assist with the below issue? I’ve been trying to write a PShell script that makes an API call to the credentials/store/system/domain/_/createCredentials endpoint, however I keep getting response status 403: No valid crumb included in the request, even if I already have added the correct header with the crumb obtained from the /crumbIssuer/api/json endpoint. CSRF is enabled. Below is my script:

=== CONFIGURATION ===

$jenkinsUrl = “”$jenkinsUser = “admin”$jenkinsApiToken = “”$githubToken = “”

=== 1. Generate the GitHub Credentials XML ===

$credentialsId = “github_keyPS”$credentialsXml = @"<com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>GLOBAL$credentialsIdGitHub Tokengit$githubToken</com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>"@

$xmlFilePath = “github_credentials.xml”$credentialsXml | Out-File -Encoding UTF8 -FilePath $xmlFilePath

=== 2. Get Jenkins Crumb ===

$crumbUrl = “$jenkinsUrl/crumbIssuer/api/json”$headers = @{ Authorization = “Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(”${jenkinsUser}:${jenkinsApiToken}")) }

try {$crumbResponse = Invoke-RestMethod -Uri $crumbUrl -Headers $headers -Method GetWrite-Host $crumbResponse} catch {Write-Error “Failed to get Jenkins crumb. $_”exit 1}

=== 3. Upload Credentials to Jenkins ===

$credentialsApiUrl = “$jenkinsUrl/credentials/store/system/domain/_/createCredentials”$headers[“Content-Type”] = “application/xml”$headers[$crumbResponse.crumbRequestField] = $crumbResponse.crumb$headers

try {$response = Invoke-RestMethod -Uri $credentialsApiUrl                                    -Method Post-Headers $headers                                    -InFile $xmlFilePath-ContentType “application/xml”Write-Host “GitHub credentials uploaded successfully.”} catch {Write-Error “Failed to upload credentials. $_”}

Are you sure you’re using an api token? Normally when you use an api token a crumb is not required.