Export ALL attachments.

Hi all!

I need to export our ticket data weekly to be compliant. 

With that export, i also do need to periodically download all the attachments.

Now i know this question was already asked once, but that answer isnt an answer, its a pointer that i cannot divert to an answer.

How (step by step) do i download all my attachments and in such a manner that its connected to the CSV export of the ticket data (so correct attachment to the correct ticket).

And why isnt there a download button to do so? (i guess more customers need to comply to have a full backup of their data)

Thanks to anyone who can answer :)

  • Hello  
    Thank you for your question. 

    I am trying to understand the use case and what exactly are you trying to do, if you can please add more information. Thanks.

    Anyway, as part of our export mechanism and  the Backup, you have a column named: "Attachments links" and you can access the attachment of each incident through the links.

  • Hi  , thanks for your time. Yes the links i have, but i need the full attachments. For audit we need to have a copy of our data ("in control of your data"), so ticket data and the attachments. Let's say Solarwinds got hacked and there is no access to our data, therefore we need that offline copy. 

    Thanks X!

  •   Thank you for the information.
    You can download all the attachments by a script that will open the attachment link and download it .

    The authentication is done through SWSD, therefore you must be logged in to your SWSD account.

  • Thanks for your answer  , do you have an example script? 

  • Hello rinat.gil

    Were you able to provide an example script for Rowmeister to download attachments? I would very much appreciate it if I could receive any script examples you can provide.

    Thanks

  • Howdy  and  !

    To use the SolarWinds Service Desk API to retrieve all attachments from tickets, you need to make a series of API calls. The API calls will need to first list all tickets and then fetch attachments for each ticket. SolarWinds Service Desk API uses RESTful principles and provides endpoints to interact with different resources, including tickets and their attachments.

    Below, I'll provide a general outline on how to script these API calls, including a JSON example for the necessary GET request. Please note that you will need an API token to authenticate your requests.

    Step 1: Obtain an API Token

    First, you need to have an API token from SolarWinds Service Desk. To retrieve this, see our documentation page.

    Step 2: List All Tickets

    You'll start by fetching all tickets. The endpoint to get all tickets might look something like this:

    GET https://api.samanage.com/incidents.json Authorization: Bearer your_api_token

    This endpoint will return a list of tickets. You need to handle pagination to fetch all tickets if there are more tickets than fit in one page. Check the response headers for pagination links.

    Step 3: Fetch Attachments for Each Ticket

    For each ticket, use the ticket ID to fetch attachments. The endpoint for getting attachments from a ticket could look like this:

    GET api.samanage.com/.../attachments.json Authorization: Bearer your_api_token

    Replace {ticket_id} with the actual ID of the ticket.

    Step 4: Script Example

    You can automate this process using a script. Below is a Python script example that demonstrates these steps using the requests library. You will need Python installed and the requests library which you can install using pip install requests.

    import requests def get_api(url, headers): response = requests.get(url, headers=headers) if response.status_code == 200: return response.json() else: print("Failed to fetch data:", response.status_code, response.text) return None def main(): api_token = 'your_api_token' base_url = 'https://api.samanage.com' headers = { 'Authorization': f'Bearer {api_token}', 'Accept': 'application/json' } # Fetch all tickets tickets = get_api(f"{base_url}/incidents.json", headers) if tickets: for ticket in tickets: ticket_id = ticket['id'] # Fetch attachments for each ticket attachments = get_api(f"{base_url}/incidents/{ticket_id}/attachments.json", headers) if attachments: for attachment in attachments: print(f"Ticket ID {ticket_id} has attachment: {attachment['name']} URL: {attachment['url']}") if __name__ == "__main__": main()

    Step 5: Execute and Store

    Run the script to fetch all the attachments. You may need to modify the script to handle pagination fully or adjust fields according to your specific needs. Also, consider error handling and rate limiting compliance as per SolarWinds API guidelines.

    Note:

    • Always secure your API token.
    • Adjust the API endpoints if there have been updates or changes in the SolarWinds Service Desk API.
    • Make sure to test the script in a development environment before running it in production.
  • Dear all,

    Thanks for the guidance, i have written a script that should work, but when i insert my created API key i receive the 401 error, not authorised.

    What am i doing wrong? This script should work and even showing download status.

    Thanks, Ro

    # Parameters
    param (
        [string]$apiKey = "YOUAPIKEYHERE",
        [string]$apiEndpoint = "https://apieu.samanage.com",
        # API endpoint can be api.samanage.com
        [string]$outputDirectory = "C:\DATA\Attachments"
    
    )
    
    
    # Function to call the API
    function Invoke-SolarWindsAPI {
        param (
            [string]$url,
            [string]$method = "GET",
            [hashtable]$headers = @{},
            [object]$body = $null
        )
    
        $headers.Add("Authorization", "Bearer $apiKey")
        $headers.Add("Accept", "application/json")
        $headers.Add("Content-Type", "application/json")
    
        try {
            $response = Invoke-RestMethod -Uri $url -Method $method -Headers $headers -Body ($body | ConvertTo-Json -Depth 100)
            return $response
        } catch {
            Write-Host "Error accessing $url"
            Write-Host $_.Exception.Message
        }
    }
    
    # Ensure the output directory exists
    if (-Not (Test-Path -Path $outputDirectory)) {
        New-Item -ItemType Directory -Path $outputDirectory
    }
    
    # Fetch all incidents (tickets)
    $incidentsUrl = "$apiEndpoint/incidents.json"
    Write-Host "Fetching incidents from $incidentsUrl"
    $incidents = Invoke-SolarWindsAPI -url $incidentsUrl
    
    if ($null -eq $incidents) {
        Write-Host "No incidents found or error fetching incidents."
        exit
    }
    
    # Initialize progress bar
    $totalIncidents = $incidents.Count
    $incidentCounter = 0
    
    Write-Host ("Starting download of attachments for {0} incidents..." -f $totalIncidents)
    
    # Loop through each incident (ticket) and fetch its attachments
    foreach ($incident in $incidents) {
        $incidentCounter++
        $incidentNumber = $incident.number
        $attachmentsUrl = "$apiEndpoint/incidents/$($incident.id)/attachments.json"
        Write-Host "Fetching attachments from $attachmentsUrl"
        $attachments = Invoke-SolarWindsAPI -url $attachmentsUrl
    
        if ($null -eq $attachments) {
            Write-Host "No attachments found or error fetching attachments for incident #$incidentNumber."
            continue
        }
    
        Write-Host ("Processing incident {0} of {1}: Incident #{2}" -f $incidentCounter, $totalIncidents, $incidentNumber)
    
        # Loop through each attachment
        $totalAttachments = $attachments.Count
        $attachmentCounter = 0
    
        foreach ($attachment in $attachments) {
            $attachmentCounter++
            $attachmentUrl = "$apiEndpoint/attachments/$($attachment.id).json"
            Write-Host "Downloading attachment from $attachmentUrl"
            $attachmentContent = Invoke-SolarWindsAPI -url $attachmentUrl
    
            if ($null -eq $attachmentContent) {
                Write-Host "Error downloading attachment $attachmentCounter of $totalAttachments for incident #$incidentNumber."
                continue
            }
    
            # Define the output file name
            $fileName = "{0}-{1}" -f $incidentNumber, $attachment.fileName
            $outputFilePath = Join-Path -Path $outputDirectory -ChildPath $fileName
    
            # Save the attachment
            [System.IO.File]::WriteAllBytes($outputFilePath, [System.Convert]::FromBase64String($attachmentContent))
    
            Write-Host ("Downloaded attachment {0} of {1} for incident #{2}" -f $attachmentCounter, $totalAttachments, $incidentNumber)
        }
    }
    
    Write-Host ("Download complete. All attachments have been saved to {0}" -f $outputDirectory)