Skip to main content

Integrations

TypeBase PathTrigger Name
REST resource~{realm}/integrations/Not currently supported.
RPC resourceoauth-tokenN/A.

This resource holds all published OAuth 2.0 integrations ("apps"), as well as your own integrations (even those not yet published). It's only possible to modify the integrations you have created yourself; all other integrations are read-only.

See OAuth Authorization Code Flow for more information about how to use OAuth 2.0 with Onslip 360.

Endpoints

NameMethodRelative PathPayloadResponseDescription
addIntegrationPOST~{realm}/integrations/IntegrationStored_IntegrationAdds a new integration to the list.
listIntegrationsGET~{realm}/integrations/N/AStored_Integration[]Retrieves a list of integrations.
getIntegrationGET~{realm}/integrations/{id}N/AStored_IntegrationRetrieves an integration.
putIntegrationPUT~{realm}/integrations/{id}IntegrationStored_IntegrationReplaces an integration.
updateIntegrationPATCH~{realm}/integrations/{id}Partial_IntegrationStored_IntegrationUpdates specified integration fields.
removeIntegrationDELETE~{realm}/integrations/{id}N/AN/ADeletes an integration.
requestOAuthAccessTokenPOSToauth-tokenOAuthAuthorizationCodeRequestOAuthAccessTokenResponseThe OAuth 2.0 Token Endpoint.

The requestOAuthAccessToken Endpoint

Once the user has authorized the integration and is redirected back to your redirect_uri endpoint, you should exchange the provided authorization code for an AccessToken using the requestOAuthAccessToken endpoint. It's a standard OAuth 2.0 Token Endpoint, except that PKCE is mandatory.

note

Like all other endpoints, this endpoint negotiates Entity Format based on the Accept header. To fully comply with the OAuth 2.0 specification, unless you're not using one of our SDKs, the response should be forced to application/json by appending .json to the endpoint URI, like this: https://test.onslip360.com/v1/oauth-token.json.

This endpoint is not scoped to a specific realm (since you don't know the realm of the user who authorized the integration yet). Instead, you should use the realm property in the response to determine what company alias to use once the access token has been obtained.

tip

If you use one of the SDKs we provide, you can use the oauthPKCE() utility function to generate a fresh code_challenge/code_verifier key pair.

Just submit an OAuthAuthorizationCodeRequest payload and, if all goes well, the server will respond with an OAuthAccessTokenResponse response. You will find the Hawk key ID in the access_token property and the actual Hawk key value in the secret property. The company alias to use is provided in the realm property; if a location was requested, you'll find its ID in the location property as well.

For integrations supporting external journals, the journal property will contain the ID of the journal to use. To bind/create an external journal as part of the authorization flow, the integration/client must request the add-external-records permission. Adding external-journal to the features list is optional but recommended if your integration requires external journals.

Permissions

PermissionDescription
edit-integrationsClient is allowed to add new integrations and to modify or delete existing integrations owned by this realm.
show-integrationsClient is allowed to query the integration list and to fetch individual integrations.
use-integrationsClient is allowed to activate/authorize a private or 3rd party integration.

Entities

Interface Integration

namespace Integration {
export type Confinement = 'authorization' | 'location' | 'user';
export type Type = 'oauth';
}

interface Integration {
'alias': string;
'name': string;
'type': Integration.Type;
'name-t9n'?: Translation[];
'description'?: string;
'description-t9n'?: Translation[];
'icon'?: File;
'author': string;
'email': string;
'web-address': string;
'categories'?: StatusEvent.Category[];
'status-uri'?: string;
'permissions': Permission[];
'features': CompanyFeature.Flag[];
'confinements': Integration.Confinement[];
'oauth-redirect-uris': string[];
'id'?: number;
'created'?: DateTime;
'updated'?: DateTime;
'deleted'?: DateTime;
'updated-by'?: number;
'updated-from'?: number;
'tags'?: string[];
'labels'?: number[];
}
PropertyData TypeDescription
aliasStringThe integration alias (OAuth 2.0 client ID). Must be unique.
nameStringThe name of the integration. Must be unique.
typeIntegration.TypeAlways set to oauth for now.
name-t9nTranslation[]?Translations of name.
descriptionString?A short description of the integration.
description-t9nTranslation[]?Translations of description.
iconFileArchive.File?An icon/logo for the integration.
authorStringThe author of the integration.
emailStringAn email address where users can get information and support for the integration.
web-addressStringA link to to a web page where users can get information and support for the integration.
categoriesStatusEvent.Category[]?A set of categories the integration is applicable to.
status-uriURI?An URI that accepts a POST:ed IntegrationStatusMessage and returns a SystemStatus payload in order to retrieve the integration's current status.
permissionsPermission[]A set of permissions the integration requires.
featuresCompanyFeature.Flag[]A set of feature flags required by the integration.
confinementsIntegration.Confinement[]A set of modifiers specifying how the AccessToken will be generated. See below.
oauth-redirect-urisURI[]A set of OAuth 2.0 redirection endpoint URIs used by the integration.
idInt64?The resource ID of this entity.
createdDateTime?Date and time when this entity was first created.
updatedDateTime?Date and time when this entity was last modified.
deletedDateTime?Date and time when this entity was deleted.
updated-byInt64?ID of User who last modified this entity.
updated-fromInt64?ID of Till (trusted device) which last modified this entity.
labelsInt64[]?A list of Label IDs associated with this entity.

By specifying relevant categories, your integration may be featured/checked in relevant sections in the Onslip 360 Backoffice.

To let the user know of problems or issues with your integration or its configuration, you can optionally provide a status-uri that accepts a POST:ed IntegrationStatusMessage and returns a SystemStatus response.

The confinements property determines how the resulting AccessToken will be generated. It is specified as a combination of the following flags.

ConfinementDescription
authorizationA new access token will be generated for each authorization and previous authorizations, if any, will remain untouched.
locationThe access token will be bound to a specific location.
userThe access token will be owned by the current user and is considered personal.

If confinements includes authorization, any previously generated access token for this integration will remain valid, and a new token will be created each time the integration is activated. The user will be asked to provide a name for the token, so it's clear what the token is used for (like a particular mobile device, for instance).

If confinements includes location, the generated access token is scoped to a particular Location by including the location ID in the token's alias property. The user will be asked to specify what location should be used as part of the authorization flow. Except for this, there are no special properties or restrictions associated with the token.

If confinements includes user, the token will be belong to the user in question. If not present, on the other hand, a service user will first be created, which will be the owner of the access token. This is appropriate if the integration is not personal and should remain active even if the user who activated it is later removed.

If confinements is empty, it means that a service user will be created, the token will not be bound to any location and if any user re-authorizes the integration, the previous authorization will be revoked and replaced by the new one.

Interface IntegrationStatusMessage

This interface is somewhat similar to the WebHookMessage interface.

export interface IntegrationStatusMessage {
'service-endpoint-uri': string;
'company-alias': string;
'integration-alias': string;
'access-token'?: string;
}
PropertyData TypeDescription
service-endpoint-uriStringAn API URI where the Onslip 360 server is available. Use this URI if you need to fetch more data or perform server operations as part of the web hook processing.
company-aliasStringThe realm from where the integration status is requested.
integration-aliasStringThe alias of the integration whose status is requested.
access-tokenString?The Hawk ID of the integration's access token, if the integration is enabled and active.

service-endpoint-uri is provided so you can easily recognize what Onslip 360 environment (staging, production etc.) the status request comes from. company-alias (the customer realm/company alias) and integration-alias (your Client ID) might also be of interest to you, but it's the access-token that, if provided, exactly specifies the integration instance that should be checked. If set, it matches the access_token property of the OAuthAccessTokenResponse message you received when the integration was activated.

Finally, just like web hooks may be authenticated, these status request will also be Hawk-authenticated using the integration's access token (if there is one). This way you can ensure that it's actually Onslip 360 that is requesting the status check and not some malicious third party.

Interface SystemStatus

export interface SystemStatus {
'events': StatusEvent[];
}
PropertyData TypeDescription
eventsStatusEvent[]A list of status events.

Interface StatusEvent

export namespace StatusEvent {
export type Category = 'activation' | 'any' | 'accounting' | 'orders' | 'payments' | 'sales' | 'stock-balances';
}

export interface StatusEvent {
'log-level': TriggerAction.LogLevel;
'category': StatusEvent.Category;
'description'?: string;
'status-message': string;
'server-error'?: ServerError;
}
PropertyData TypeDescription
log-levelTriggerAction.LogLevelThe log level of the event.
categoryStatusEvent.CategoryThe category of the event.
descriptionString?A description of the event. Used as a heading (overriding category) when displaying the event to the user.
status-messageStringThe event's status message.
server-errorServerError?If the event is an error, additional error details.

The events (and integrations) are organized using the following categories:

CategoryDescription
anyThe event/integration is not related to any particular category.
accountingThe event/integration is related to accounting/bookkeeping.
activationThe event/integration is related to the activation of the integration or the generated access token.
ordersThe event/integration is related to orders.
paymentsThe event/integration is related to payments, like custom payment methods and invoicing.
salesThe event/integration is related to sales, like sales reports or other financial insights.
stock-balancesThe event/integration is related to stock balances.

Status events reuse the log levels for triggers.

Log levelDescription
errorsAn error event.
warningsA warning event.
resultsAn informational event.
progressInformation about an operation currently in progress, like if the integration is currently syncing data and cannot report mismatches at this time.
allA debug event.

Interface OAuthAuthorizationCodeRequest

interface OAuthAuthorizationCodeRequest {
'grant_type': string;
'client_id': string;
'redirect_uri': string;
'code': string;
'code_verifier': string;
}
PropertyData TypeDescription
grant_typeStringMust be set to authorization_code.
client_idStringThe alias (client ID) of the integration to activate.
redirect_uriStringThe exact redirection endpoint URI used when authorization code was requested.
codeStringThe authorization code returned by the authorization code flow.
code_verifierStringThe PKCE code verifier.

Interface OAuthAccessTokenResponse

interface OAuthAccessTokenResponse {
'token_type': string;
'access_token': string;
'secret': string;
'algorithm': string;
'realm': string;
'scope'?: string;
'journal'?: number;
'location'?: number;
}
PropertyData TypeDescription
token_typeStringAlways Hawk.
access_tokenStringThe Hawk key identifier.
secretStringThe Hawk key secret (the raw value; not Base 64-encoded).
algorithmStringAlways sha256.
realmStringThe realm/company alias.
scopeString?If you were not granted all permissions you asked for, a space-separated list of permissions you did receive.
journalInt64?If the token is bound to an external journal, the ID of the journal to use.
locationInt64?If the token is bound to a location (i.e., confinements includes location), the ID of the location to use.