Requesting an Access Token
In order to retrieve an access token, you must have a ClientId and ClientSecret
The access token is an encrypted JWT OAuth 2.0 bearer token which contains authorization information (user claims)
It must be included in the HTTP header when accessing restricted resource endpoints (findings, audits, users, etc..)
Token Lifetime
Your access token will have a limited lifetime, so you'll need to reauthenticate each time the token expires
An access token can be requested multiple times, which will not invalidate any previous tokens
For more information, see: Authentication
Sample Code
The following C# code sample implements a request to retrieve an access token:
public async Task<string> GetAccessToken()
{
var tokenRequest = new TokenRequest
{
ClientId = "YOUR_CLIENT_ID",
ClientSecret = "YOUR_CLIENT_SECRET",
};
var httpClient = new HttpClient();
var content = new StringContent(JsonConvert.SerializeObject(tokenRequest), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync("https://app.ease.io/public/api/v1/Auth/token", content);
var responseContent = await response.Content.ReadAsStringAsync();
var tokenResponse = JsonConvert.DeserializeObject<TokenResponse>(responseContent);
return tokenResponse.AccessToken;
}
Sample Request Object
public class TokenRequest
{
public string ClientId { get; set; }
public string ClientSecret { get; set; }
}
Sample Response Object
public class TokenResponse
{
public string AccessToken { get; set; }
public DateTime Expires { get; set; }
}
Retrieving a List of Findings
Once an access token is retrieved, you can then use that access token to retrieve a list of findings
The following C# code samples show how we can retrieve a list of findings that were opened in the last 30 days
Please review Findings Section for more options on filtering down the findings list
public async Task<IEnumerable<FindingsListItemResponse>> GetFindings()
{
var accessToken = await GetAccessToken();
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var findingsRequest = new FindingsListRequest
{
OpenDateFrom = DateTime.UtcNow.AddDays(-30),
};
var content = new StringContent(JsonConvert.SerializeObject(findingsRequest), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync("https://app.ease.io/public/api/v1/Findings/filter", content);
if (!response.IsSuccessStatusCode)
{
throw new Exception($"Failed to retrieve findings. Status code: {response.StatusCode}");
}
var responseContent = await response.Content.ReadAsStringAsync();
var findingsResponse = JsonConvert.DeserializeObject<PagedResponse<FindingsListItemResponse>>(responseContent);
return findingsResponse.Items;
}
Sample Request Object
public class FindingsListRequest
{
public DateTime? OpenDateFrom { get; set; }
public DateTime? OpenDateTo { get; set; }
}
Sample Response Objects
public class FindingsListItemResponse
{
public int Id { get; set; }
public string AuditDescription { get; set; }
public NameResponse ResponsibleParty { get; set; }
public NameResponse ApprovingParty { get; set; }
public StatusResponse Status { get; set; }
public DateTime? DueDate { get; set; }
public DateTime? OpenDate { get; set; }
public DateTime? ClosedDate { get; set; }
public NameResponse Program { get; set; }
public NameResponse Urgency { get; set; }
public NameResponse Location { get; set; }
public NameResponse Site { get; set; }
public NameResponse FindingType { get; set; }
public NameResponse Category { get; set; }
public NameResponse SubCategory { get; set; }
public string AuditorComments { get; set; }
public string QuestionTitle { get; set; }
public NameResponse Countermeasure { get; set; }
public string FindingComments { get; set; }
public string FindingClosingComments { get;set; }
public string ApprovingPartyComments { get; set; }
}
public class PagedResponse<T> where T : class, new()
{
public int PageSize { get; set; }
public int CurrentPage { get; set; }
public int TotalItems { get; set; }
public int TotalPages { get; set; }
public IList<T> Items { get; set; }
public PagedResponse()
{
Items = new List<T>();
}
}
public class NameResponse
{
public int Id { get; set; }
public string Name { get; set; }
}
public class StatusResponse
{
public int Code { get; set; }
public string Name { get; set; }
}
Closing a Finding
In order to close out a finding, you must first determine the findingId
This can be done using the platform UI, or by using the Findings List API
Please review Close Finding Section to review list of rules for closing a finding
public async Task CloseFinding(int findingId)
{
var accessToken = await GetAccessToken();
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var request = new CloseFindingRequest
{
ClosingComments = "Finding resolved",
};
var content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
var response = await httpClient.PutAsync($"https://app.ease.io/public/api/v1/Findings/{findingId}/close", content);
if (!response.IsSuccessStatusCode)
{
throw new Exception($"Failed to close finding. Status code: {response.StatusCode}");
}
}
Sample Request Object
public class CloseFindingRequest
{
public string ClosingComments { get; set; }
}
Updating a Finding
Certain properties of a Finding can be updated as long as that finding is not Completed
To see which properties can be updated, see Update Finding endpoint
In the example below, we'll show how you can update the ResponsiblyPartyId in order to reassign a Finding
Prior to calling the API to reassign a Finding, it is recommended that you first call the Finding Lookup endpoint to determine the available options that are used to update that Finding
For example, we'll first call the Finding Lookup endpoint to determine all available users that can be assigned this Finding
public async Task<IEnumerable<NameResponse>> GetResponsiblePartyUsers(int findingId)
{
var finding = await GetFindingLookup(findingId);
return finding.ResponsibleParties;
}
public async Task<FindingLookup> GetFindingLookup(int findingId)
{
var accessToken = await GetAccessToken();
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var response = await httpClient.GetAsync($"https://app.ease.io/public/api/v1/Findings/{findingId}/lookup");
if (!response.IsSuccessStatusCode)
{
throw new Exception($"Failed to retrieve finding. Status code: {response.StatusCode}");
}
var responseContent = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<FindingLookup> (responseContent);
}
Sample Response Object
public class FindingLookup
{
public List<NameResponse> ResponsibleParties { get; set; }
public List<NameResponse> ApprovingParties { get; set; }
public List<NameResponse> Countermeasures { get; set; }
public bool CountermeasuresEnabled { get; set; }
public bool CategoriesEnabled { get; set; }
}
Once we have found the ID of the user we would like to reassign the Finding to, we can then make a call to the Update Finding endpoint
public async Task UpdateFindingResponsibleParty(int findingId, int userId)
{
var accessToken = await GetAccessToken();
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var request = new UpdateFindingRequest
{
ResponsiblePartyId = userId
};
var content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
var response = await httpClient.PutAsync($"https://app.ease.io/public/api/v1/Findings/{findingId}/update", content);
if (!response.IsSuccessStatusCode)
{
throw new Exception($"Failed to update finding. Status code: {response.StatusCode}");
}
}
Sample Request Object
public class UpdateFindingRequest
{
public int? CategoryId { get; set; }
public int? SubCategoryId { get; set; }
public int? ResponsiblePartyId { get; set; }
public int? ApprovingPartyId { get; set; }
public int? UrgencyId { get; set; }
public int? CountermeasureId { get; set; }
public DateTime? DueDate { get; set; }
public string FindingClosingComments { get; set; }
}
Comments
0 comments
Please sign in to leave a comment.