📘

Enterprise API

This feature is only available to customers with an enterprise Platform subscription. Please get in touch to discuss enabling it on your account.

The Commissioning API allows developers to add special actions to Thngs that represent their commissioning and decommissioning within the manufacturing process. The API makes use of special built-in action types to delineate these actions with special intent from regular actions.

An action of the commissions type represents a commissioning event, where a Thng is linked to a product resource representing its SKU at the point of manufacture where it can be said to be of that SKU.

Similarly, an action of the decommissions type represents the decommissioning of an item that will not be sold in market, due to some defect or other reason preventing its sale. Note that an item must have been commissioned before it can be decommissioned.

When a Thng is to be commissioned, it must meet the following requirements:

  • Have an action of type encodings, from when it was encoded into a tag.
  • Have customFields.factory set to its factory identifier.
    • This must match the factoryMetadata.factory value in the commissioning request.
    • This must match the identifiers.factory in the place representing the factory.

API Status
Beta:
/thngs/:thngIdentifier/actions/commissions
/thngs/:thngIdentifier/actions/decommissions
/thngs/:thngIdentifier/commissionState


CommissionDocument Data Model

.product (string, required)
    Any valid product identifier separated from its value by 
    ':'.

.location (LocationDocument, required)
    An object representing a location. Either 'position' or 
    'place' us required.

.purchaseOrder (string)
    Purchase order for which the commission happened

.occurredAt (string, required)
    Date and time of commission in ISO8601 format with time 
    offset

.factoryMetadata (FactoryMetadataDocument)
    Object describing information about the factory.
{
  "type": "object",
  "description": "Object describing a commissioning event.",
  "required": ["product", "location", "occurredAt"],
  "properties": {
    "product": {
      "type": "string",
      "description": "Any valid product identifier separated from its value by ':'.",
      "example": "gs1:01:02374837684278"
    },
    "location": {
      "additionalProperties": false,
      "type": "object",
      "description": "An object representing a location. Either 'position' or 'place' us required.",
      "properties": {
        "position": {
          "type": "object",
          "description": "A GeoJSON Point object. The coordinate order is longitude, then latitude.",
          "required": ["type", "coordinates"],
          "properties": {
            "type": {
              "type": "string",
              "description": "The type of the point.",
              "enum": ["Point"]
            },
            "coordinates": {
              "type": "array",
              "description": "The point coordinates",
              "items": {
                "type": "number",
                "minimum": -180,
                "maximum": 180
              }
            }
          }
        },
        "createdAt": {
          "type": "integer",
          "description": "Timestamp when the resource was created.",
          "readOnly": true,
          "minimum": 0
        },
        "timestamp": {
          "type": "integer",
          "description": "The time the location update occurred, or filled automatically by the Platform if omitted.",
          "readOnly": true
        },
        "longitude": {
          "type": "number",
          "description": "The longitude."
        },
        "latitude": {
          "type": "number",
          "description": "The latitude."
        },
        "place": {
          "type": "string",
          "description": "The place ID.",
          "pattern": "^[abcdefghkmnpqrstwxyABCDEFGHKMNPQRSTUVWXY0123456789]{24}$"
        },
        "scopes": {
          "additionalProperties": false,
          "type": "object",
          "description": "Project and user scopes arrays.",
          "required": ["users", "projects"],
          "properties": {
            "users": {
              "type": "array",
              "description": "An array of Application User IDs this resource is scoped to.",
              "items": { "type": "string" }
            },
            "projects": {
              "type": "array",
              "description": "An array of project IDs this resource is scoped to.",
              "items": {
                "type": "string",
                "description": "The ID of this resource.",
                "pattern": "^[abcdefghkmnpqrstwxyABCDEFGHKMNPQRSTUVWXY0123456789]{24}$",
                "readOnly": true
              }
            }
          }
        }
      },
      "x-filterable-fields": ["timestamp"]
    },
    "purchaseOrder": {
      "type": "string",
      "description": "Purchase order for which the commission happened"
    },
    "occurredAt": {
      "description": "Date and time of commission in ISO8601 format with time offset",
      "type": "string",
      "format": "date-time"
    },
    "factoryMetadata": {
      "type": "object",
      "description": "Object describing information about the factory.",
      "required": ["factory"],
      "properties": {
        "factory": {
          "description": "Identifier of a factory. This value should match \"identifiers.factory\" of the place referenced in \"location.place\" field and match \"customFields.factory\" value of a Thng.",
          "type": "string",
          "example": 123141414
        },
        "supplier": {
          "description": "ID of a supplier",
          "type": "string",
          "example": 574574363
        },
        "zone": {
          "description": "Name of the zone within the factory",
          "type": "string",
          "example": "Line 65"
        }
      }
    }
  }
}
{
  "product": "gs1:01:05000157089908",
  "purchaseOrder": "2300003783",
  "occurredAt": "2019-01-25T09:19:00Z",
  "factoryMetadata": {
    "factory": "gs1:414:87923487"
  },
  "location": {
    "position": {
      "type": "Point",
      "coordinates": [
        -0.080050,
        51.527668
      ]
    }
  }
}

See also: LocationDocument, FactoryMetadataDocument


FactoryMetadataDocument Data Model

.factory (string)
    Identifier of a factory. This value should match
    "identifiers.factory" of the place referenced in
    "location.place" field and match "customFields.factory"
    value of a Thng.

.supplier (string)
    ID of a supplier

.zone (string)
    Name of the zone within the factory
{
  "type": "object",
  "properties": {
    "factory": {
      "description": "Identifier of a factory. This value should match \"identifiers.factory\" of the place referenced in \"location.place\" field and match \"customFields.factory\" value of a Thng.",
      "type": "string",
      "example": 123141414
    },
    "supplier": {
      "description": "ID of a supplier",
      "type": "string",
      "example": 574574363
    },
    "zone": {
      "description": "Name of the zone within the factory",
      "type": "string",
      "example": "Line 65"
    }
  }
}
{
  "factory": "gs1:414:87923487"
}

DecommissionDocument Data Model

.location (LocationDocument, required)
    An object representing a location. Either 'position' or 
    'place' us required.

.occurredAt (string, required)
    Date and time of commission in ISO8601 format with time 
    offset

.factoryMetadata (FactoryMetadataDocument)
    Object describing information about the factory.
{
  "type": "object",
  "description": "Object describing a decommissioning event.",
  "required": ["location", "occurredAt"],
  "properties": {
    "location": {
      "additionalProperties": false,
      "type": "object",
      "description": "An object representing a location. Either 'position' or 'place' us required.",
      "properties": {
        "position": {
          "type": "object",
          "description": "A GeoJSON Point object. The coordinate order is longitude, then latitude.",
          "required": ["type", "coordinates"],
          "properties": {
            "type": {
              "type": "string",
              "description": "The type of the point.",
              "enum": ["Point"]
            },
            "coordinates": {
              "type": "array",
              "description": "The point coordinates",
              "items": {
                "type": "number",
                "minimum": -180,
                "maximum": 180
              }
            }
          }
        },
        "createdAt": {
          "type": "integer",
          "description": "Timestamp when the resource was created.",
          "readOnly": true,
          "minimum": 0
        },
        "timestamp": {
          "type": "integer",
          "description": "The time the location update occurred, or filled automatically by the Platform if omitted.",
          "readOnly": true
        },
        "longitude": {
          "type": "number",
          "description": "The longitude."
        },
        "latitude": {
          "type": "number",
          "description": "The latitude."
        },
        "place": {
          "type": "string",
          "description": "The place ID.",
          "pattern": "^[abcdefghkmnpqrstwxyABCDEFGHKMNPQRSTUVWXY0123456789]{24}$"
        },
        "scopes": {
          "additionalProperties": false,
          "type": "object",
          "description": "Project and user scopes arrays.",
          "required": ["users", "projects"],
          "properties": {
            "users": {
              "type": "array",
              "description": "An array of Application User IDs this resource is scoped to.",
              "items": { "type": "string" }
            },
            "projects": {
              "type": "array",
              "description": "An array of project IDs this resource is scoped to.",
              "items": {
                "type": "string",
                "description": "The ID of this resource.",
                "pattern": "^[abcdefghkmnpqrstwxyABCDEFGHKMNPQRSTUVWXY0123456789]{24}$",
                "readOnly": true
              }
            }
          }
        }
      },
      "x-filterable-fields": ["timestamp"]
    },
    "occurredAt": {
      "description": "Date and time of commission in ISO8601 format with time offset",
      "type": "string",
      "format": "date-time"
    },
    "factoryMetadata": {
      "type": "object",
      "description": "Object describing information about the factory.",
      "required": ["factory"],
      "properties": {
        "factory": {
          "description": "Identifier of a factory. This value should match \"identifiers.factory\" of the place referenced in \"location.place\" field and match \"customFields.factory\" value of a Thng.",
          "type": "string",
          "example": 123141414
        },
        "supplier": {
          "description": "ID of a supplier",
          "type": "string",
          "example": 574574363
        },
        "zone": {
          "description": "Name of the zone within the factory",
          "type": "string",
          "example": "Line 65"
        }
      }
    }
  }
}
{
  "occurredAt": "2019-01-26T09:19:00Z",
  "factoryMetadata": {
    "factory": "gs1:414:87923487"
  },
  "location": {
    "position": {
      "type": "Point",
      "coordinates": [
        -0.080050,
        51.527668
      ]
    }
  }
}

See also: LocationDocument, FactoryMetadataDocument


Specifying Commissioning Resources

Thngs and products are specified within the Commissioning API by one of their identifiers in a URL-friendly format (instead of id, as elsewhere in the API). This allows a much more flexible approach when the id required is not known, or requires extra work to obtain.

For example, the following Thng with identifiers:

{
  "id": "UMen7ds4s6HKsBRRarB4FArq",
  "createdAt": 1548407786579,
  "updatedAt": 1548407786579,
  "name": "Example Thng",
  "identifiers": {
    "gs1:21": "32874"
  },
  "customFields": {
    "factory": "gs1:414:87923487"
  }
}

would be specified as follows, using the final : as the key-value separator:

gs1:21:32874

Commission a Thng

The process of commissioning a Thng requires knowledge of its identifiers, the identifiers of the product to be associated, the production line name, and the location where the commissioning took place (such as a factory or warehouse). The date and time of commissioning (vs that of the request itself) can be explicitly set using the occurredAt property.

🚧

Note

Before commissioning, a Thng must have been encoded. This is done using a regular action of the encodings type, at the point that the Thng has been encoded in barcode or similar.

POST /thngs/:thngIdentifier/actions/commissions
Authorization: $OPERATOR_API_KEY
Content-Type: application/json

CommissionDocument
curl -H "Content-Type: application/json" \
  -H "Authorization: $OPERATOR_API_KEY" \
  -X POST 'https://api.evrythng.com/thngs/gs1:21:32874/actions/commissions' \
  -d '{
    "product": "gs1:01:05000157089908",
    "purchaseOrder": "2300003783",
    "occurredAt": "2019-01-25T09:19:00Z",
    "factoryMetadata": {
      "factory": "gs1:414:87923487"
    },
    "location": {
      "position": {
        "type": "Point",
        "coordinates": [
          -0.080050,
          51.527668
        ]
      }
    }
  }'
const thngIdentifier = 'gs1:21:32874';
const payload = {
  product: 'gs1:01:05000157089908',
  purchaseOrder: '2300003783',
  occurredAt: '2019-01-25T09:19:00Z',
  factoryMetadata: {
    factory: 'gs1:414:87923487',
  },
  location: {
    position: {
      type: 'Point',
      coordinates: [
        -0.080050,
        51.527668
      ]
    }
  }
};

operator.thng(thngIdentifier).action('commissions')
  .create(payload)
  .then(console.log);

The response is similar to that of Creating an action, but includes the purchaseOrder in its customFields.

As the desired side-effect, the Thng will now have product assigned based on the product identifier provided in the request. The Thng is now considered to be commissioned.

HTTP/1.1 201 Created
Content-Type: application/json

{
  "id": "UqV4N2FwpQWbRUwwRmkRwxfm",
  "createdAt": 1548408960778,
  "customFields": {
    "purchaseOrder": "2300003783",
    "factory": "gs1:414:87923487"
  },
  "timestamp": 1548408960778,
  "type": "commissions",
  "location": {
    "latitude": 51.527668,
    "longitude": -0.08005,
    "position": {
      "type": "Point",
      "coordinates": [
        -0.08005,
        51.527668
      ]
    }
  },
  "locationSource": "unknown",
  "context": {
    "ipAddress": "141.0.154.202",
    "city": "City of London",
    "region": "England",
    "countryCode": "GB",
    "userAgent": "ReactorNetty/0.8.4.RELEASE",
    "timeZone": "Europe/London"
  },
  "thng": "UMen7ds4s6HKsBRRarB4FArq",
  "product": "U5sHN4k8CynCtcwRwGTXGsVp"
}

Read Thng Commissioning State

The commissioning state of a given Thng can be read at any time.

GET /thngs/:thngIdentifier/commissionState
Authorization: $OPERATOR_API_KEY
curl -H "Authorization: $OPERATOR_API_KEY" \
  -X GET 'https://api.evrythng.com/thngs/gs1:21:34786/commissionState'
const thngIdentifier = 'gs1:21:34786';

operator.thng(thngIdentifier)
  .commissionState()
  .read();

The response state will be one of commissioned, decommissioned, and not_commissioned (if commissioning never took place).

HTTP/1.1 200 OK
Content-Type: application/json

{
  "state": "commissioned"
}

Decommission a Thng

In the event an item must be decommissioned, a corresponding decommissions special action request should be made including the location and occurredAt of the decommissioning (vs that of the request), using the same formats as for commissioning.

POST /thngs/:thngIdentifier/actions/decommissions
Authorization: $OPERATOR_API_KEY
Content-Type: application/json

DecommissionDocument
curl -H "Content-Type: application/json" \
  -H "Authorization: $OPERATOR_API_KEY" \
  -X POST 'https://api.evrythng.com/thngs/gs1:21:34786/actions/decommissions' \
  -d '{
    "occurredAt": "2019-01-26T09:19:00Z",
    "factoryMetadata": {
      "factory": "gs1:414:87923487"
    },
    "location": {
      "position": {
        "type": "Point",
        "coordinates": [
          -0.080050,
          51.527668
        ]
      }
    }
  }'
const thngIdentifier = 'gs1:21:34786';
const payload = {
  occurredAt: '2019-01-26T09:19:00Z',
  factoryMetadata: {
    factory: 'gs1:414:87923487'
  },
  location: {
    position: {
      type: 'Point',
      coordinates: [
        -0.080050,
        51.527668
      ]
    }
  }
};

operator.thng(thngIdentifier).action('decommissions')
  .create(payload)
  .then(console.log);
HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": "UMBnPhMes6n5PewRa7frwqXn",
  "createdAt": 1548412868140,
  "timestamp": 1548412868140,
  "type": "decommissions",
  "customFields": {
    "factory": "gs1:414:87923487"
  },
  "location": {
    "latitude": 51.527668,
    "longitude": -0.08005,
    "position": {
      "type": "Point",
      "coordinates": [
        -0.08005,
        51.527668
      ]
    }
  },
  "locationSource": "unknown",
  "context": {
    "ipAddress": "141.0.154.202",
    "city": "City of London",
    "region": "England",
    "countryCode": "GB",
    "userAgent": "ReactorNetty/0.8.4.RELEASE",
    "timeZone": "Europe/London"
  },
  "thng": "UMen7ds4s6HKsBRRarB4FArq"
}