Skip to main content

Requests and Responses

While the IssuuSDK provides standard operations supported by the Issuu API, it is possible to craft your own requests if the IssuuSDK does not currently support an operation you need.

Requests

The IssuuSDK provides two request types, IssuuRequest and IssuuRequest<TData>. These are defined here: https://github.com/IngeniumSE/IssuuSDK/blob/main/libs/IssuuSDK/IssuuRequest.cs

The latter IssuuRequest<TData> inherits from IssuuRequest but is tailored towards sending payload data to the Issuu API.

File Content

You'd still need to use IssuuRequest for sending payload data where that payload is a file, as IssuuRequest<TData> will use JSON serialization on TData as the payload.

Mapping HTTP responses

A mapping delegate, MapResponse<TResponse> is provided for passing mapping functions to the FetchAsync code API. This is defined as:

public delegate Task<MappedResponse<TResponse>> MapResponse<TResponse>(
HttpResponseMessage response, CancellationToken cancellationToken);

The mapping delegate must accept a HTTP response message, and return a MappedResponse<TResponse>, which will contain the result data, and any additional metadata and links.

Example:

async Task<MappedResult<Document[]>> MapAsync(HttpResponse response, CancellationToken ct)
{
DataContainer<TResponse>? data = default;
Meta? meta = default;
Dictionary<string, string>? links = default;
if (response.Content is not null)
{
data = await response.Content.ReadFromJsonAsync<DataContainer<TResponse>>(
_deserializerOptions, cancellationToken)
.ConfigureAwait(false);

if (data is not null)
{
if (data.Count.HasValue && data.PageSize.HasValue)
{
meta = new()
{
PageSize = data.PageSize.Value,
TotalItems = data.Count.Value,
TotalPages = (int)Math.Ceiling(data.Count.Value / (double)data.PageSize.Value)
};
}

if (data.Links is { Count: > 0 })
{
links = new();
foreach (var link in data.Links)
{
links.Add(link.Key, link.Value.Href);
}
}
}
}
}

var request = new IssuuRequest(...);
await client.FetchAsync<Document>(
request,
$"/drafts",
MapAsync,
cancellationToken);
)
Only Success Results

You do not need to worry about mapping an error response from the Issuu API, as the IssuuSDK will handle this automatically. When your mapping delegate is called, this is for a success HTTP status code

Internally, the IssuuSDK makes use of this approach combined with specific container types which can be deserialized from the JSON responses.

DataContainer<TResult> container type

This container type is used when returning set operations, where TResult is the array of the intended type:

PropertyTypeNotes
Countint?The total number of items
PageSizeint?The size of the page
ResultsTData?The data
LinksDictionary<string, LinkContainer>?The set of links for the resource

For example, when using the Drafts.GetDraftsAsync(...) operation, internally a DataContainer<Document[]> is used which returns a set of documents.

Single Results

The DataContainer<T> type is only used for results that return sets of data. For individual result instances, such as a single document, the JSON result is directly deserialized, not in a wrapping type.

This container type is used to deserialize a link:

This container type is used to deserialzie a specific error message:

PropertyTypeNotes
HrefstringThe error message

ErrorContainer container type

This container type is used to deserialize an error response:

PropertyTypeNotes
FieldsDictionary<string, ErrorMessageContainer>?The set of field errors
DetailsDictionary<string, ErrorMessageContainer>?The set of specific error details
MessagestringThe error message

ErrorMessageContainer container type

This container type is used to deserialzie a specific error message:

PropertyTypeNotes
MessagestringThe error message

HTTP GET example - returning a single resource

var request = new IssuuRequest(
HttpMethod.Get,
$"/drafts/{slug}"
);

var response = await apiClient.FetchAsync<Document>(
request,
async httpResponse => await Map(httpResponse)
);

In the above example, we're crafting a HTTP GET request to the https://api.issuu.com/v2/drafts/{slug} resource, where {slug} is the document slug, and then mapping the response back as a Document. The response instance will be of type IssuuResponse<Document>.

Transforming HTTP responses

The FetchAsync method provides a mapping function that allows you to transform your HttpResponse into your requested type. You will be responsible for transforming the HttpContent into your desired type.

The IssuuSDK does provide some container types for desializing the raw JSON content, where you know the expected shape of the output.

HTTP GET example - returning a set of resources, with a query string

var request = new IssuuRequest(
HttpMethod.Get,
$"/drafts/",
new QueryStringBuilder()
.AddParameter("page", 1)
.AddParameter("size", 10)
.Build()
);

var response = await apiClient.FetchAsync<Document[]>(
request,
async httpResponse => await Map(httpResponse)
);

In the above example, we're crafting a HTTP GET request to the https://api.issuu.com/v2/drafts resource, and then mapping the response back as an array Document. The response instance will be of type IssuuResponse<Document[]>. You can use any collection type that is supported by deserializing a JSON array by System.Text.Json

HTTP POST example - posting payload data

var draft = new Draft();
var request = new IssuuRequest<Draft>(
HttpMethod.Post,
$"/drafts/",
draft
);

var response = await apiClient.SendAsync(request);
SendAsync vs. FetchAsync

You can utilise SendAsync when you do not expect, or do not care about any result data. FetchAsync should be used when you are expecting some output data from the Issuu API.

HTTP PATCH example - posting a file using a path

var request = new IssuuRequest(
new HttpMethod("PATCH"),
$"/drafts/{slug}/upload",
useMultipartContent: true,
filePath: "/path/to.file",
fileName: "custom_file_name.pdf",
formData: new Dictionary<string, string>
{
["confirmCopright"] = "true"
}
);

var response = await apiClient.SendAsync(request);

When posting a file, you must ensure useMultipartContent is true. Internally, the IssuuSDK will generate a bounded mutipart content container, which will contain the StreamContent for the file, and optionally any other form data, allowing you to post a file, and provide additional parameters at the same time.

If you do not provide fileName, the IssuuSDK will use the file name from the provided filePath.

HTTP PATCH example - posting a file using a stream

var stream = new FileStream("/path/to.file");

var request = new IssuuRequest(
new HttpMethod("PATCH"),
$"/drafts/{slug}/upload",
useMultipartContent: true,
fileStream: stream,
fileName: "custom_file_name.pdf",
formData: new Dictionary<string, string>
{
["confirmCopright"] = "true"
}
);

var response = await apiClient.SendAsync(request);

If you are providing a Stream, the fileName parameter is required, as this cannot be determined otherwise. Using a Stream allows you to target any stream, as long as it can be rewound.

Responses

The IssuuResponse and IssuuResponse<TData> types are used to represents responses returned by the Issuu API. The latter type, IssuuResponse<TData> is used when there is payload data in the HTTP response that you want deserialized into the TData type. These are defined here: https://github.com/IngeniumSE/IssuuSDK/blob/main/libs/IssuuSDK/IssuuResponse.cs.

Issuu API challenges

The Issuu API returns results in an often inconsistent shape that may differ from operation to operation. It is recommended to use the standard Drafts and Publications operations provided by the API client, which handles these different result shapes, but return a consistent code API shape instead.

Here are common properties on IssuuResponse:

PropertyTypeNotes
IsSuccessboolWas the HTTP status a success code?
ErrorError?The captured error (if applicable)
LinksDictionary<string, string>?Any captured links
MetaMeta?Metadata, such as paging information
StatusCodeHttpStatusCodeThe HTTP status code of the response
RateLimitingRateLimiting?Information on rate limiting
RequestMethodHttpMethodThe HTTP method used
RequestUriUriThe requested URI resource
RequestContentstring?See Developer-friendly Debugging
ResponseContentstring?See Developer-friendly Debugging

You should always check IsSuccess after receiving a response. The Error object should always have a value when IsSuccess is false.

Additional properties on IssuuResponse<TData>:

PropertyTypeNotes
DataTData?Whatever data type you are expecting
HasDataboolTrue, if valid data was deserialized from the response
IsSuccess and HasData

It may not be enough simply to check IsSuccess when handling response payload data. The HasData value is a null-check on the TData? value.

Also note though, if you are expecting a collection of items, the HasData will simply check that the collection is not null, it will not check for the presence of items within the collection.

Meta

The Meta property of the response is a colletion of pagination-related properties:

PropertyTypeNotes
PageintThe currently requested page
PageSizeintThe size of the requested page
TotalItemsintThe total number of items for the given request
TotalPagesintThe total number of pages for the given number of items

Rate Limiting

The RateLimiting property of the response is the current state of rate limiting for your authentication token. If you exceed rate limiting, the Issuu API may fail requests.

PropertyTypeNotes
RemainingintThe number of API calls remaining until reset
LimitintThe total number of API calls that can be made
ResetDateTimeOffsetThe date/time that the rate limit stats are reset
Rate Limiting

The IssuuSDK will not handle throttling of requests based on the rate limiting values that are returned. If you are performing a high volume of operations against the Issuu API, you are responsible for throttling those requests yourself.

The Links dictionary may contain additional links to related resources. The schema suggests these can be anything, but typical HATEOS-style links may be self, next, prev, but the IssuuSDK cannot guarantee these are present consistently.

Errors

The Error property will contain any captured error information by the IssuuAPI:

PropertyTypeNotes
ErrorsDictionary<string, string>?Specific field or data-level error messages
ExceptionException?The captured exception
MessagestringThe main error message
Non-API errors

If the IssuuSDK encounters issues that are not caused by the Issuu API, such as transient network faults, or an inability for the SDK to deserialize response data (perhaps for yet unsupported operations), these will also surface as a populated Error value.

Developer-friendly Debugging

The primary consumer of this SDK are developers, so the IssuuSDK has been designed to give as much information as possible to developers to aid in understanding any integration issues.

Request and Response Content

The IssuuResponse and IssuuResponse<TData> type contains useful properties for debugging requests and responses.

PropertyTypeNotes
StatusCodeHttpStatusCodeThe HTTP status code of the response
RateLimitingRateLimiting?Information on rate limiting
RequestMethodHttpMethodThe HTTP method used
RequestUriUriThe requested URI resource
RequestContentstring?The captured HTTP request content
ResponseContentstring?The captured HTTP response content

By default, the RequestContent and ResponseContent properties will not be populated, these have to be enabled in your app configuration:

{
"Issuu": {
"Token": "{token}",
"CaptureRequestContent": true,
"CaptureResponseContent": true
}
}

Alternatively, you can explicitly enable them through IssuuSettings:

var settings = new IssuuSettings
{
Token = "{token}",
CaptureRequestContent = true,
CaptureResponseContent = true
};