API Quickstart
This is a good place to get started if you haven't used Polaris APIs before.
You will need the following.
- Polaris sign-in credentials.
- Access to a project where at least one test has finished. (If it is the first test on your project, keep in mind that the first test can take longer than usual to complete, because there are steps to verify that the test ran properly. Your subscription may call for triage on the first test, which also can make the test take longer.)
This quickstart will walk you through a set of steps to get the issue data from a recent test and examine some security vulnerabilities found in the results. Retrieving issue data is the most common use of Polaris APIs.
These steps won't necessarily be the exact steps you use later when scripting API calls. If you already have some of the things that these steps retrieve, like portfolio ID and application ID, you won't need to retrieve them, and you can get your issue data more quickly. For this quickstart, we'll assume that you don't have that information and we'll help you get it from scratch. This takes a few more steps, but it's useful to know how and the process demonstrates how everything fits together in Polaris.
-
Make an access token.
Note: Access tokens expire if unused for 30 days.
- In Polaris, select your profile name, then select Account.
- Select Access Tokens.
-
Select Create New Token.
-
Enter a name for the token (limit is 255 characters) and select Save.
-
Copy the token and store it in a safe place.
Note: You only get one chance to copy the token. If it is lost, you won't be able to copy it again, but you can make a new one.Note: The API reference docs in this portal are interactive. With an access token, you can use the API reference docs to generate requests that interact with your applications and projects. After you open a service's reference docs, select Authorize. Enter your token in the Value field and select Authorize. Enter the token separately for each service you use and sign out of the service when finished.
-
Get your portfolio ID.
Purpose: The portfolio ID is needed in a subsequent step.
Request:
curl --location 'https://polaris.blackduck.com/api/portfolios/' \ --header 'accept: application/vnd.polaris.portfolios-1+json' \ --header 'Api-token: {token}'
About this request:
- Note the Api-token header. This is required for every call to Polaris APIs, although the Swagger reference docs don't append it automatically when they generate an example. In all these calls we replace the web token with a placeholder in curly brackets.
- For this operation, Polaris can retrieve the portfolio ID based on your token, because the token is associated with you and your organization, and an organization has only one portfolio.
- The header 'accept: application/vnd.polaris.portfolios-1+json' tells Polaris what kind of JSON data you expect to receive in the response. You'll see what that format looks like as soon as you send the request.
Response:
{ "_items": [ { "id": "99267011-57f4-43de-b2aa-0fd7408efax6" } ], "_links": [ { "href": "https://polaris.blackduck.com/api/portfolios/?_offset=0&_limit=100", "rel": "first", "method": "GET" }, { "href": "https://polaris.blackduck.com/api/portfolios/?_offset=0&_limit=100", "rel": "last", "method": "GET" }, { "href": "https://polaris.blackduck.com/api/portfolios/?_offset=0&_limit=100", "rel": "self", "method": "GET" } ], "_collection": { "itemCount": 1, "currentPage": 1, "pageCount": 1 } }
About this response:
- The _items property (near the top) contains the portfolio ID, which is needed in the next step.
-
Get an application ID.
Purpose: Use the portfolio ID to obtain an application ID, which is required in a subsequent step.
Request:
curl --location 'https://polaris.blackduck.com/api/portfolios/99267011-57f4-43de-b2aa-0fd7408efax6/applications' --header 'accept: application/vnd.polaris.portfolios.applications-1+json' --header 'Api-token: {token}'
About this request:
- Use the portfolio ID as an in-path parameter, between /portfolios and /applications.
- Without any optional filtering parameters, this request returns a complete list of all the applications in your organization's portfolio.
Response:
{ "_items": [ { "id": "703f7656-847d-40cb-a082-e55988369a31", "name": "Example Application One", "description": null, "subscriptionTypeUsed": "CONCURRENT", "portfolioId": "99267011-57f4-43de-b2aa-0fd7408efax6", "inTrash": false, "createdAt": "2023-08-17 18:06:43", "updatedAt": "2023-08-17 18:06:43", "autoDeleteSetting": false, "branchRetentionPeriodSetting": 30, "autoDeleteSettingsCustomized": false }, { "id": "14a180a9-af46-41a7-8d17-dc8f28c1b295", "name": "Example Application Two", "description": null, "subscriptionTypeUsed": "CONCURRENT", "portfolioId": "99267011-57f4-43de-b2aa-0fd7408efax6", "inTrash": false, "createdAt": "2023-11-23 00:17:47", "updatedAt": "2023-11-23 00:17:47", "autoDeleteSetting": false, "branchRetentionPeriodSetting": 30, "autoDeleteSettingsCustomized": false }, { "id": "1d86e38c-7fd6-4f73-8a1d-d5f146060ef1", "name": "Example Application Three", "description": "An example application for testing and documentation.", "subscriptionTypeUsed": "CONCURRENT", "portfolioId": "99267011-57f4-43de-b2aa-0fd7408efax6", "inTrash": false, "createdAt": "2023-08-08 16:12:16", "updatedAt": "2023-08-16 20:27:16", "autoDeleteSetting": false, "branchRetentionPeriodSetting": 30, "autoDeleteSettingsCustomized": false } ], "_links": [ { "href": "https://polaris.blackduck.com/api/portfolios/99267011-57f4-43de-b2aa-0fd7408efax6/applications?_offset=0&_limit=100", "rel": "first", "method": "GET" }, { "href": "https://polaris.blackduck.com/api/portfolios/99267011-57f4-43de-b2aa-0fd7408efax6/applications?_offset=0&_limit=100", "rel": "last", "method": "GET" }, { "href": "https://polaris.blackduck.com/api/portfolios/99267011-57f4-43de-b2aa-0fd7408efax6/applications?_offset=0&_limit=100", "rel": "self", "method": "GET" } ], "_collection": { "itemCount": 3, "currentPage": 1, "pageCount": 1 } }
About this response:
- The _items list contains three objects, each corresponding to a different application.
- Choose the ID of the application that interests you. That would be the one containing the project you tested.
-
Get a project ID.
Purpose: Use the application ID to obtain a project ID which is required in a subsequent step.
Request:
curl --location 'https://polaris.blackduck.com/api/portfolios/99267011-57f4-43de-b2aa-0fd7408efax6/applications/703f7656-847d-40cb-a082-e55988369a31/projects' \ --header 'accept: application/vnd.polaris.portfolios.projects-1+json' \ --header 'Api-token: {token}'
About this request:
- Use the portfolio ID as an in-path parameter, between /portfolios and /applications.
- Use the application ID as an in-path parameter, between /applications and /projects.
- Without any optional filtering parameters, this request returns a complete list of projects in the application.
Response:
{ "_items": [ { "id": "b2b34aaf-ec8f-460a-9f31-7b751dfa53c6", "name": "Example Project One", "description": "An example project for testing and documentation.", "branches": null, "applicationId": "703f7656-847d-40cb-a082-e55988369a31", "createdAt": "2024-03-01 15:30:38", "updatedAt": "2024-03-01 15:30:38" }, { "id": "53c4cd9d-b719-41bc-8e15-2923c9bc4e11", "name": "Example Project Two", "description": "An example project for testing and documentation.", "branches": null, "applicationId": "703f7656-847d-40cb-a082-e55988369a31", "createdAt": "2024-05-31 00:57:40", "updatedAt": "2024-05-31 00:57:40" }, { "id": "f5023bf4-a763-4028-8675-d9a6d5c881d5", "name": "Example Project Three", "description": "An example project for testing and documentation.", "branches": null, "applicationId": "703f7656-847d-40cb-a082-e55988369a31", "createdAt": "2023-08-17 18:08:07", "updatedAt": "2023-08-17 18:08:07" } ], "_links": [ { "href": "https://polaris.blackduck.com/api/portfolios/99267011-57f4-43de-b2aa-0fd7408efax6/applications/703f7656-847d-40cb-a082-e55988369a31/projects?_offset=0&_limit=100", "rel": "first", "method": "GET" }, { "href": "https://polaris.blackduck.com/api/portfolios/99267011-57f4-43de-b2aa-0fd7408efax6/applications/703f7656-847d-40cb-a082-e55988369a31/projects?_offset=0&_limit=100", "rel": "last", "method": "GET" }, { "href": "https://polaris.blackduck.com/api/portfolios/99267011-57f4-43de-b2aa-0fd7408efax6/applications/703f7656-847d-40cb-a082-e55988369a31/projects?_offset=0&_limit=100", "rel": "self", "method": "GET" } ], "_collection": { "itemCount": 3, "currentPage": 1, "pageCount": 1 } }
About this response:
- The application in question contains three projects. These are at the beginning of the response, as a list of objects contained in the _items property. When you go in search of your own test results, you'll likely be able to identify your project by name here.
- The _collection object describes the total number of records (the three projects), the total number of pages containing results, and the current page. This is useful when you have more records than can be viewed at one time.
- Collect the ID of the project for use in the next step.
-
Get a list of issues from the latest test in a project.
Purpose: Use a project ID collected in the previous step to get the issues in your recent test.
Request:
curl --location 'https://polaris.blackduck.com/api/findings/issues?testId=latest&_first=100&_includeType=true&_includeOccurrenceProperties=true&_includeFirstDetectedOn=true&projectId=b2b34aaf-ec8f-460a-9f31-7b751dfa53c6' \ --header 'accept: application/vnd.polaris.findings.issues-1+json' \ --header 'Accept-Language: en-CA,en;q=0.9' \ --header 'Api-token: {token}'
About this request:
- The query
testId=latest
tells Polaris to return results from the most recent test completed on this project (in this example, a SAST test). Alternatively, you could supply a testId, which can be obtained from the Bridge CLI tool or from the web UI after you start a test. - The query
_first=100
tells Polaris to provide only the first 100 records found in this search. The reference docs explain how you can grab the first or last n records, or sort the results, or filter on things like issue type, severity, or triage properties. - The query
_includeType=true
tells Polaris to include basic information about the issues, including name, description, and remidiation information. - The query
_includeOccurrenceProperties=true
tells Polaris to include additional information about the issues, including the effect of the issue, the file in which the issue was detected, the line number on which the issue was detected, … etc. - The query
_includeFirstDetectedOn=true
tells Polaris to include the date and time when the issue was first detected. - The query
projectId=b2b34aaf-ec8f-460a-9f31-7b751dfa53c6
tells Polaris to return issues detected in a specific project. Note that you must include aprojectId
orapplicationId
, but the request will return an error if you provide both.
Response:
This is a shortened version of the original response.
{ "_items": [ { "id": "C0030A7E497440BFB5A883DEFF71665A", "weaknessId": "w-27", "type": { "id": "e0c20eef-8a7a-b02f-e8a5-44c7c613edd0", "altName": "sql_injection:sink|java", "_localized": { "name": "SQL Injection", "otherDetails": [ { "key": "description", "value": "Untrusted user-supplied data is inserted into a SQL statement without adequate validation, escaping, or filtering." }, { "key": "remediation", "value": "Rewrite all SQL queries constructed through dynamic concatenation to use an injection-safe query mechanism such as prepared statements with parameterized queries.\n\nMost modern programming languages provide a feature called \"parameterized queries\" that allow user-supplied data to be inserted safely as values in dynamic SQL queries. Rather than construct the dynamic SQL query by concatenating user-supplied data to static SQL query string fragments, data values are identified in the query by parameter markers or variables. Dynamic data is then passed through a mechanism provided by SQL that prevents the supplied data from changing the meaning of the query.\n\nNote: the exact syntax and use of prepared statements with parameterized queries vary from language to language." } ] } }, "occurrenceProperties": [ { "key": "local-effect", "value": "A user can change the intent of the SQL query, which may inappropriately disclose or corrupt data within the database." }, { "key": "language", "value": "Java" }, { "key": "severity", "value": "high" }, { "key": "filename", "value": "SqlInjectionLesson4.java" }, { "key": "line-number", "value": 57 }, { "key": "cwe", "value": "CWE-89" }, { "key": "coverity-events", "value": "f85e6ee57e99f597f0714a235bf409f16d6e1d7f70bd25b043455b630e5bdbb6" }, { "key": "location", "value": "webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson4.java" } ], "firstDetectedOn": "2024-12-17T20:40:50.22Z", "_cursor": "AAAABA==", "_links": [ { "href": "https://polaris.blackduck.com/api/findings/issues/C0030A7E497440BFB5A883DEFF71665A?projectId=b2b34aaf-ec8f-460a-9f31-7b751dfa53c6&_includeType=true&_includeOccurrenceProperties=true&_includeTriageProperties=true&_includeFirstDetectedOn=true", "rel": "self", "method": "GET" }, { "href": "https://polaris.blackduck.com/api/findings/issues/C0030A7E497440BFB5A883DEFF71665A/triage-history?projectId=b2b34aaf-ec8f-460a-9f31-7b751dfa53c6", "rel": "triage-history", "method": "GET" }, { "href": "https://polaris.blackduck.com/api/findings/issues/C0030A7E497440BFB5A883DEFF71665A/detection-history?projectId=b2b34aaf-ec8f-460a-9f31-7b751dfa53c6", "rel": "detection-history", "method": "GET" }, { "href": "https://polaris.blackduck.com/api/findings/occurrences/1eecc203-6318-69fb-890d-fb9f84e6a98b?projectId=b2b34aaf-ec8f-460a-9f31-7b751dfa53c6", "rel": "occurrence", "method": "GET" }, { "href": "https://polaris.blackduck.com/api/findings/occurrences/1eecc203-6318-69fb-890d-fb9f84e6a98b/snippet?projectId=b2b34aaf-ec8f-460a-9f31-7b751dfa53c6", "rel": "snippet", "method": "GET" }, { "href": "https://polaris.blackduck.com/api/findings/occurrences/1eecc203-6318-69fb-890d-fb9f84e6a98b/assist?projectId=b2b34aaf-ec8f-460a-9f31-7b751dfa53c6", "rel": "assist", "method": "GET" }, { "href": "https://integration-api.securecodewarrior.com/api/v1/trial?Id=blackduck_polaris&MappingList=cwe&MappingKey=89&LanguageKey=Java", "rel": "secure-code-warrior", "method": "GET" } ], "_type": "issues" }, [...] ], "_links": [ { "href": "https://polaris.blackduck.com/api/findings/issues?testId=latest&_includeType=true&_includeOccurrenceProperties=true&_includeTriageProperties=true&_includeFirstDetectedOn=true&projectId=b2b34aaf-ec8f-460a-9f31-7b751dfa53c6&_first=100", "rel": "self", "method": "GET" }, { "href": "https://polaris.blackduck.com/api/findings/issues?testId=latest&_includeType=true&_includeOccurrenceProperties=true&_includeTriageProperties=true&_includeFirstDetectedOn=true&projectId=b2b34aaf-ec8f-460a-9f31-7b751dfa53c6&_first=100", "rel": "first", "method": "GET" }, { "href": "https://polaris.blackduck.com/api/findings/issues?testId=latest&_includeType=true&_includeOccurrenceProperties=true&_includeTriageProperties=true&_includeFirstDetectedOn=true&projectId=b2b34aaf-ec8f-460a-9f31-7b751dfa53c6&_last=100", "rel": "last", "method": "GET" }, { "href": "https://polaris.blackduck.com/api/findings/issues?testId=latest&_includeType=true&_includeOccurrenceProperties=true&_includeTriageProperties=true&_includeFirstDetectedOn=true&projectId=b2b34aaf-ec8f-460a-9f31-7b751dfa53c6&_cursor=AAAAZA%3D%3D&_first=100", "rel": "next", "method": "GET" } ], "_collection": { "itemCount": 1100, "pageCount": 11, "_type": "issues" } }
About this response:
- The _collection property at the end of this paginated response explains how much data there is. The test returned a total of 1100 issues. Since the request included the _first=100 query, that's how many issues were returned on this one page. The remaining 10 pages in the page count, contain the other 1000 issues.
- The reference documentation explains how to page through the remaining results.
- The _items object in this response is trimmed down to contain just one of the 100 issues returned in the response.
- The query