Add attachments to change requests using attachment API

  • Release version: Xanadu
  • Updated July 31, 2025
  • 2 minutes to read
  • Summarize
    Summarized using AI
    This content was generated using new OpenAI-powered functionality. Results are provided on an as is basis and are not guaranteed to be accurate or complete.

    Summary of Add attachments to change requests using attachment API

    This guide explains how to add attachments, such as test report XML files, to ServiceNow change requests using the Attachment API. This capability is useful for customers integrating DevOps tools with ServiceNow, enabling automated upload of relevant files directly to change request records.

    Show full answer Show less

    The Attachment API endpoint follows the format:

    https://<yourinstance>.service-now.com/api/now/attachment/file?tablename=changerequest&tablesysid=<changesysid>&filename=<attachmentfilename.xml>

    Key parameters include:

    • tablename: Must be set to changerequest
    • tablesysid: The sysid of the target change request record
    • filename: The desired name of the attached file

    Prerequisites

    • Create an active ServiceNow user with Web service access only enabled.
    • Assign the role snchangewrite to this user to enable writing attachments to change requests.
    • Ensure the system property sndevops.enableadogenericconnection is enabled for Azure DevOps integration.
    • When configuring Azure DevOps, use a generic connection with a user holding the snchangewrite role for uploading attachments to the change request table.

    Integration Examples with DevOps Tools

    Azure DevOps

    Use provided pipeline YAML snippets to retrieve the change request sysid and post attachments using the REST API task. The example demonstrates posting an XML file named test3.xml to the change request.

    GitHub

    GitHub pipelines can similarly be configured to POST attachments to change requests using the Attachment API, following patterns akin to Azure DevOps examples.

    Jenkins

    Sample Jenkins pipeline scripts illustrate how to:

    • Invoke REST API calls with authentication to post test data.
    • Retrieve change request sysid dynamically via API calls.
    • Upload XML attachments to the corresponding change request.

    Scripts use Groovy and shell commands to handle authentication and API interactions.

    Important Considerations

    • The size of the XML attachment must be acceptable by the orchestration tool used (e.g., Azure DevOps, Jenkins).
    • For Azure DevOps, the user performing the attachment upload must have the snchangewrite role for authorization.

    By following these instructions, ServiceNow customers can automate the attachment of test reports or other files to change requests, improving traceability and integration between DevOps pipelines and change management processes.

    Add test report xmls as attachments to DevOps change requests using the attachment API.

    For more information about the API, see Attachment - POST /now/attachment/file.

    The attachment API URL is:

    https://<your_instance>.service-now.com/api/now/attachment/file?table_name=change_request&table_sys_id=$(getServerChange.sys_id)&file_name=<attached_filename.xml>, where
    • table_name = 'change_request'
    • table_sys_id = <chg record sys_id>
    • file_name = Any name for the attachment

    Azure DevOps

    Prerequisites

    • Create an active user with the option Web service access only selected. For information on how to create a user, see Create a user.
    • Assign the role sn_change_write to the user. For information on how to assign the role, see Assign a role to a user.

      Create user.

    • The system property sn_devops.enable_ado_generic_connection must be enabled.
    • While configuring your Azure DevOps project, to upload to chg. table, the generic connection used should have a user having the role sn_change_write.

    For Azure DevOps pipelines, use the format given here to add attachments to change requests.

    Sample pipeline:
    stage: PostDeploy
        jobs:
          - job: 'pd1'
            pool: server
            steps:
               - task: ServiceNow-DevOps-Server-Get-Change@1
                 inputs:
                   connectedServiceName: 'v01-Software Quality Scans-ServiceNow DevOps Service Connection'
                   projectName: '$(system.teamProject)'
                   pipelineName: '$(build.definitionName)'
                   stageName: 'Deploy'
                   jobName: 'd1'
                   buildNumber: '$(build.buildId)'
                   branchName: '$(Build.SourceBranchName)'
                 name: getServerChange  
               - task: InvokeRESTAPI@1
                 inputs:
                   connectionType: 'connectedServiceName'
                   serviceConnection: 'v01 - new'
                   method: 'POST'
                   body: '<root><name>john2</name><age>34</age></root>'
                   urlSuffix: 'api/now/attachment/file?table_name=change_request&table_sys_id=$(getServerChange.changeSysId)&file_name=test3.xml'
                   waitForCompletion: 'false'

    Azure DevOps pipeline.

    GitHub

    For GitHub pipelines, use the format given here to add attachments to change requests.

    Sample pipeline:

    GitHub pipeline.

    Attachment in the Change Request form in Now instance:

    Attachments in change record.

    Jenkins

    For Jenkins pipelines, use the format given here to add attachments to change requests.

    Sample pipeline:
    pipeline {
        agent any
        
        stages {
            stage('POST API Call') {
                steps {
                    script {
                        def apiUrl = 'https://<your_instance>.service-now.com/api/sn_devops/v1/devops/tool/test?toolId=<devops_ToolId>&testType=Smoke'
                        def requestBody = [
                            name: "Smoke tests",
                            duration: 0.0,
                            passedTests: 1,
                            failedTests: 1,
                            skippedTests: 1,
                            blockedTests: 1,
                            totalTests: 4,
                            startTime: "2023-12-14T23:31:31z",
    	                    finishTime: "2023-12-15T23:31:31z",
                            buildNumber: env.BUILD_NUMBER,
                            stageName: "POST API Call",
                            pipelineName: "TestPipelineKL"
                        ]
                        
                        def auth = "<password>" // devops.integration.user:<password> in base64 encoded.
                        def authHeader = "Basic " + auth
                        
                        def response = httpRequest(
                            contentType: 'APPLICATION_JSON',
                            httpMode: 'POST',
                            requestBody: groovy.json.JsonOutput.toJson(requestBody),
                            url: apiUrl,
                            customHeaders: [[name: 'Authorization', value: authHeader]]
                        )
                        
                        if (response.status == 200 || response.status == 201) {
                            echo "API call successful!"
                            echo "Response: ${response.content}"
                        } else {
                            error "API call failed with status ${response.status}"
                        }
                    }
                }
            }
            stage('UAT deploy') {
                        steps {
                            script {
                                def chg_output = snDevOpsChange()
                                def changeRequestNumber = snDevOpsGetChangeNumber(changeDetails: """{"build_number":"${env.BUILD_NUMBER}", "pipeline_name": "TestPipelineKL", "stage_name": "UAT deploy"}""")
                                echo "${changeRequestNumber}"
                                echo "Output of snDevOpsChange(): ${chg_output}"
                        }
                    }
            }
            stage('Example') {
                steps {
                    script {
                        def API_URL = 'https://<your_instance>.service-now.com/api/sn_devops/devops/orchestration/changeInfo?pipelineName=TestPipelineKL&toolId=<devops_ToolId>&buildNumber=' + env.BUILD_NUMBER + '&stageName=UAT%20deploy'
                        def AUTH = 'Basic <password>'
                        // Call the API
                        def response = sh(script: "curl -X GET -H 'Authorization: ${AUTH}' -H 'Content-Type: application/json' '${API_URL}'", returnStdout: true).trim()
                        echo "Response: ${response}"
                        
                        // Store the JSON response into a variable
                        def slurper = new groovy.json.JsonSlurper()
                        def jsonResponse = slurper.parseText(response)
                        echo "Stored JSON Response: ${jsonResponse}"
                        
                        // Store the specific field value from JSON response into a variable
                        def changeId = jsonResponse.result.sys_id
                        echo "Change ID: ${changeId}"
                        
                        // Call the second API to post attachment
                        def xmlData = '<root><name>john2</name><age>34</age></root>'
                        def AUTH2 = 'Basic <password>='
                        def postResponse = sh(script: "curl -X POST -H 'Authorization: ${AUTH2}' -H 'Content-Type: application/xml' -d '${xmlData}' 'https://<your_instance>.service-now.com/api/now/attachment/file?table_name=change_request&table_sys_id=${changeId}&file_name=test10111.xml'", returnStdout: true).trim()
                    }
                }
            }
        }
    }
    

    Jenkins pipeline.

    Limitations of the attachment API

    • The attachment xml file’s text size should be acceptable to the orchestration tool.
    • For Azure DevOps, sn_change_write role is needed for authentication of attachment API, to upload the file to the change record.