Timewriting API (1.1.0)

Download OpenAPI specification:Download

The Timewriting API is an open API covering the HR area. It's an example API used to demonstrate the api-first-workbench and has not been implemented.

This document describes upcoming release v1.1.0. We recommend using documentation published at https://equinor.github.io/api-first-workbench/v1.1.0 as it provides the best developer experience. Information on the next release v1.2.0 is available at this page

Introduction

The API is designed and built according to Equinor's API strategy.

The API is documented in OpenAPI 3.0 format and follows REST principles.

Terminology

The API will use common terminology used across the Oil&Gas industry.

API versioning

api-version must be present in all request as part of the query string. Requests without API version will be rejected with a HTTP 404 response code. The latest api-version is v1.

The api-version will stay stable over time as the API follows the principles of API evolution

Subscription key

Subscription key must be created from Equinor's API Portal for the consumer application and each request must have the HTTP header Ocp-Apim-Subscription-Key present with this value.

Authentication and authorization overview

The user executing the API requests will need to authenticate with OAuth 2.0 authorization code flow with Equinor Azure AD as the identity provider.

Modelling of resources

Resources

The resource will be named according to common terminology used across the Oil&Gas industry (for example Norsok standard NS-EN 13306 and ISO 14224).

Example of resources are /time-entries and /cost-objects.

Resource keys

Resources keys will indicate the resource type as part of the name. Example: timeEntryId and costObjectId.

Dates

All date and time information are based on UTC (Universal Time Coordinated) and formatted according to RFC3339

This also applies to durations, such as 1 day or 2 hours, which are encoded as P0Y0M1DT0H0M0S and P0Y0M0DT2H0M0S.

These values are easily compatible with time libraries such as moment.js library.

Modelling of endpoints

Operation - Lookup

Lookup operations return a single instance for the resource based on the key.

The resource may have related data which may or may not be relevant for a client. In order to indicate which related data to include, the lookup operation may provide include-... query string boolean options. Example: include-time-entries

Operation - Search/Filter

Clients need to retrieve a subset of all resources for an endpoint. Usually, the criteria are non-trivial and in many case are not direct properties of the resource. REST does not provide a well-defined pattern for these types of requests.

Our approach, is to provide predefined filters with parameters. Each filter is documented in the OpenAPI specification.

Operation - Update

Update operations for resources will utilize a sub-set of the JSON Patch proposed standard. JSON Patch is described in RFC 6902 with a user-friendly version at http://jsonpatch.com/.

Our goals with using JSON Patch is to focus on the intent of the update and avoid common pitfalls for the client. The common pitfalls we avoid with JSON Patch are:

  1. Clients inadvertently resetting properties of a resource to an empty value. This due to the client mistakenly sending all properties of a resource in a HTTP PATCH request with some of them having an initial value.
  2. Clients inadvertently overwriting changes made by other users directly in the back-end system. This due to client mistakenly have provided properties which have not been changed in a HTTP PATCH request.

Using JSON Patch is straightforward.

  • Set the content-type to application/json-patch+json.
  • In the body, send an array of JSON Patch operations. Typically, one element pr property to be update for the resource

As part of the OpenAPI documentation, we will provide concrete examples for all update operation. In addition, the schema definiton for the request body defines which resource properties can be updated.

Example of JSON Patch request body which replaces the value of the properties title and text:

[
  {
    "op": "replace",
    "path": "/comment ",
    "value": "New comment"
  },
  {
    "op": "replace",
    "path": "/hours",
    "value": 4
  }
]

HTTP Response codes

HTTP response codes will follow established best practice for REST services and will be documented in the OpenAPI specification.

Below is a list of status codes used in the API which the client should handle. Common:

  • 400 Bad Request - The request is invalid. For example missing parameters in the query string
  • 401 Unauthorized - The request did not include an authentication token or the authentication token was expired or invalid
  • 403 Forbidden - User does not have sufficient permissions
  • 405 Method not allowed - HTTP verb not supported for requested resource
  • 500 Internal Server Error - Sorry, an unexpected error occured on our side. Let's us know and we'll get around to fix it
  • 503 Service unavailable - API or a service it depends on is currently not available.

Read - HTTP GET:

  • 200 OK - The request completed successfully
  • 404 Not Found - The resource does not exist or an non-existing endpoint has been called

Create - HTTP POST:

  • 201 Created - Create of resource was successful and resource is returned in body
  • 400 Bad Request - The resource provided in the body is not according to specification
  • 409 Conflict - The creation of this resource is in conflict with an already existing resources

Create - HTTP PUT:

  • 204 No Content - Request successful but no resource returned in body

Update - HTTP PATCH:

  • 200 OK - Update of resource was successful and resource is returned in body
  • 400 Bad Request - The resource properties to update is not according to specification
  • 409 Conflict - The update of this resource is in conflict with an already existing resources

Delete - HTTP DELETE:

  • 204 No Content - Request successful but no resource returned in body
  • 409 Conflict - The deletion of this resource is not possible

Deprecation

Deprecation policy

The API will use the principles of API evolution instead of introducing a new api-version on every breaking change.

In order to achieve this, endpoints, query parameters and resource properties can become deprecated and will be marked so in the OpenAPI specification.

In general, depcrated properties will be removed after 3 months. If a client uses a deprecated endpoint or query parameter, the API will in the response provide a Sunset HTTP header Sunset: Sat, 15 May 2021 12:59:59 GMT representing the removal date for the deprecated feature as specified in RFC8594. In addition, a HTTP header Link: <https://equinor.github.io/maintenance-api-docs/#section/Deprecation>; rel="sunset" will be provided to pointing to relevant documentation.

Clients must monitor these messages and take corrective actions.

Endpoints with deprecation

None

Feature requests

Feature requests are welcomed and can be submitted through:

Authentication

bearerAuth

Security Scheme Type OAuth2
authorizationCode OAuth Flow
Authorization URL: https://login.windows.net/common/oauth2/authorize?resource=0e595101-1f08-4ce0-8684-148b2e2b8e18
Token URL: https://login.microsoftonline.com/common/oauth2/token
Scopes:

    apiKey

    Subscription key created from https://api.equinor.com

    Security Scheme Type API Key
    Header parameter name: ocp-apim-subscription-key

    New endpoints

    Endpoints which are introduces in the current version

    Create single time entry

    Overview

    Create single time entry for logged on user.

    Clients should expect end users to have prexisting knowledge of the cost object to use for a time entry, but can assist them by providing suggestions based on earlier time entries from endpoint /calendar/{start-date}/{end-date}. A general search for cost objects used in the company will not be provided as it increases the risk for wrong time writing.

    The time entry will need approval by the task owner of the cost object after registration. It's recommended to provide a comment where possible in order ease the approval process. If the approver does not have enough information, the time entry will be sent back to the end user through the workflow inbox of the ERP system.

    The client is recommended to verify that the cost object exist and is open for time writing through the endpoint /cost-objects/{cost-object-id}.

    Important information

    The endpoint does not currently support clock times. If logged on user is configured for clock times, the request will fail with a 409 - Conflict error.

    The request will fail with a 409 - Conflict error if the date is more than 3 months in the past.

    Authorizations:
    Request Body schema: application/json

    Time entry create

    date
    required
    string <date>

    Time entry date

    hours
    required
    number <double> [ 0 .. 24 ]

    Number of hours worked

    costObjectTypeId
    required
    string (CostObjectTypes)
    Enum: "wbs" "network"

    Type of cost object

    costObjectId
    required
    string

    Cost object identifier

    costSubObjectId
    string

    Secondary cost object identifier. Not use for all cost object types.

    comment
    string <= 40 characters

    Comment for time entry

    Responses

    Request samples

    Content type
    application/json
    Example
    {
    • "date": "2021-11-04",
    • "hours": 8,
    • "costObjectTypeId": "wbs",
    • "costObjectId": "C.BAX.30.xxx",
    • "comment": "Analysis of task xyz"
    }

    Response samples

    Content type
    application/json
    {
    • "timeEntryId": "154632395",
    • "date": "2021-11-04",
    • "hours": 7.5,
    • "costObjectTypeId": "wbs",
    • "costObjectId": "C.BAX.30.xxx",
    • "costSubObjectId": "",
    • "costObjectDescription": "Project XYZ",
    • "comment": "string"
    }

    Modified endpoints

    Endpoints which have been modified in the current version

    Calendar

    Calendar represent a date range to perform time writing for based on expecations in the work scehdule

    Lookup calendar for a date range

    Overview

    TBD

    Authorizations:
    path Parameters
    start-date
    required
    string <date>
    Example: 2021-11-01
    end-date
    required
    string <date>
    Example: 2021-11-01
    query Parameters
    include-time-entries
    boolean
    Default: true

    Include all time entries in the calendar

    Responses

    Request samples

    curl --request GET \
      --url 'https://api-dev.gateway.equinor.com/api-first-workbench/calendar/%7Bstart-date%7D/%7Bend-date%7D?include-time-entries=SOME_BOOLEAN_VALUE' \
      --header 'ocp-apim-subscription-key: REPLACE_KEY_VALUE'

    Response samples

    Content type
    application/json
    {
    • "startDate": "2021-11-04",
    • "endDate": "2021-11-10",
    • "days": [
      • {
        }
      ]
    }

    Time entries

    Time entry represent hours registered on a specific day towards a cost object

    Create single time entry

    Overview

    Create single time entry for logged on user.

    Clients should expect end users to have prexisting knowledge of the cost object to use for a time entry, but can assist them by providing suggestions based on earlier time entries from endpoint /calendar/{start-date}/{end-date}. A general search for cost objects used in the company will not be provided as it increases the risk for wrong time writing.

    The time entry will need approval by the task owner of the cost object after registration. It's recommended to provide a comment where possible in order ease the approval process. If the approver does not have enough information, the time entry will be sent back to the end user through the workflow inbox of the ERP system.

    The client is recommended to verify that the cost object exist and is open for time writing through the endpoint /cost-objects/{cost-object-id}.

    Important information

    The endpoint does not currently support clock times. If logged on user is configured for clock times, the request will fail with a 409 - Conflict error.

    The request will fail with a 409 - Conflict error if the date is more than 3 months in the past.

    Authorizations:
    Request Body schema: application/json

    Time entry create

    date
    required
    string <date>

    Time entry date

    hours
    required
    number <double> [ 0 .. 24 ]

    Number of hours worked

    costObjectTypeId
    required
    string (CostObjectTypes)
    Enum: "wbs" "network"

    Type of cost object

    costObjectId
    required
    string

    Cost object identifier

    costSubObjectId
    string

    Secondary cost object identifier. Not use for all cost object types.

    comment
    string <= 40 characters

    Comment for time entry

    Responses

    Request samples

    Content type
    application/json
    Example
    {
    • "date": "2021-11-04",
    • "hours": 8,
    • "costObjectTypeId": "wbs",
    • "costObjectId": "C.BAX.30.xxx",
    • "comment": "Analysis of task xyz"
    }

    Response samples

    Content type
    application/json
    {
    • "timeEntryId": "154632395",
    • "date": "2021-11-04",
    • "hours": 7.5,
    • "costObjectTypeId": "wbs",
    • "costObjectId": "C.BAX.30.xxx",
    • "costSubObjectId": "",
    • "costObjectDescription": "Project XYZ",
    • "comment": "string"
    }

    Lookup single time entry

    Overview

    Lookup a single time entry. Time entry represent hours registered on a specific day towards a cost object.

    Important information

    Consider using the endpoint /calendar/{start-date}/{end-date} for retrieving all time entries in the date range.

    Authorizations:
    path Parameters
    time-entry-id
    required
    string
    Example: 154632395

    Responses

    Request samples

    curl --request GET \
      --url https://api-dev.gateway.equinor.com/api-first-workbench/time-entries/%7Btime-entry-id%7D \
      --header 'ocp-apim-subscription-key: REPLACE_KEY_VALUE'

    Response samples

    Content type
    application/json
    {
    • "timeEntryId": "154632395",
    • "date": "2021-11-04",
    • "hours": 7.5,
    • "costObjectTypeId": "wbs",
    • "costObjectId": "C.BAX.30.xxx",
    • "costSubObjectId": "",
    • "costObjectDescription": "Project XYZ",
    • "comment": "string"
    }

    Update single time entry

    Overview

    Update single time entry.

    Supports:

    • Update comment
    • Update hours
    • Update date
    Authorizations:
    path Parameters
    time-entry-id
    required
    string
    Example: 154632395
    Request Body schema: application/json

    Time entry update

    Array ()
    op
    string
    Value: "replace"

    JSON Patch operation according to RFC6902.

    path
    string
    Enum: "/date" "/hours" "/comment"

    Path indicating the property to be impacted by the operation

    string or number

    Value to be assigned to a resource property based on the operation and path.

    Responses

    Request samples

    Content type
    application/json
    Example
    [
    • {
      • "op": "replace",
      • "path": "/hours",
      • "value": 7.5
      }
    ]

    Response samples

    Content type
    application/json
    {
    • "timeEntryId": "154632395",
    • "date": "2021-11-04",
    • "hours": 7.5,
    • "costObjectTypeId": "wbs",
    • "costObjectId": "C.BAX.30.xxx",
    • "costSubObjectId": "",
    • "costObjectDescription": "Project XYZ",
    • "comment": "string"
    }

    Delete single time entry

    Overview

    Delete single time entry.

    Authorizations:
    path Parameters
    time-entry-id
    required
    string
    Example: 154632395

    Responses

    Request samples

    curl --request DELETE \
      --url https://api-dev.gateway.equinor.com/api-first-workbench/time-entries/%7Btime-entry-id%7D \
      --header 'ocp-apim-subscription-key: REPLACE_KEY_VALUE'

    Response samples

    Content type
    application/json
    {}

    Cost objects

    Cost object represent how the cost for each time entry is allocated

    Lookup single cost object

    Overview

    Lookup a single cost object.

    The cost object is used when creating a new time entry.

    Authorizations:
    path Parameters
    cost-object-id
    required
    string
    Example: C.BAX.30.xxx

    Responses

    Request samples

    curl --request GET \
      --url https://api-dev.gateway.equinor.com/api-first-workbench/cost-objects/%7Bcost-object-id%7D \
      --header 'ocp-apim-subscription-key: REPLACE_KEY_VALUE'

    Response samples

    Content type
    application/json
    {
    • "costObjectId": "9000000",
    • "type": "wbs",
    • "costObject": "Project XYZ",
    • "isOpenForTimeWriting": true,
    • "subObjects": [
      • {
        }
      ]
    }