Mass-scale ADI Generation

The EVRYTHNG Platform is built to create, manage, and enhance resources on a very large scale. The main kinds of resources or ADIs (Active Digital Identity) that typically exist in large quantities are Thngs. Thngs represent unique instances of a product SKU, and so the ratio between Thng resources and their products is quite high.

You can create Thngs in several ways. For testing purposes and simple projects, you create them one by one through the Dashboard or through the API. To create thousands or tens of thousands of Thngs in that way would take a long time.

To make mass creation of Thngs faster and easier, the EVRYTHNG Platform includes the ADI Orders API. An ADI order can be thought of as a single instruction to create multiple Thngs to a strict specification. An example could be "create 10 Thngs for the Blue T-shirt product, each containing the shipped and boxed tags". These Thngs are given a serialized identifier and an optional redirection and can be linked to a purchase order.

Both the ADI order and the Thngs created can include additional tags, identifiers and customFields to suit the use-case.

This walkthrough demonstrates how to use ADI orders for some of the most common use-cases:

  • Generate Thngs from a list of supplied IDs.
  • Generate Thngs using IDs in a provided CSV file.
  • Generate Thngs that use the GS1 Digital Link feature.

Thngs from a list of IDs

The most common use case when generating multiple Thngs is to create them using a list of existing IDs or serial numbers.

The example described earlier, expressed as an ADI order resource, would look like the following. Note the metadata field that corresponds to the specification above and the list of ids used for each Thng.

{
  "metadata": {
    "identifierKey": "serial_id",
    "product": "pid:38497",
    "tags": [
      "shipped",
      "boxed"
    ],
    "shortDomain": "tn.gg",
    "defaultRedirectUrl": "https://evrythng.com?id={shortId}"
  },
  "purchaseOrder": "893456798",
  "ids": [
    "3829645",
    "3829646",
    "3829647",
    "3829648",
    "3829649",
    "3829650",
    "3829651",
    "3829652",
    "3829653",
    "3829654"
  ],
  "tags": [
    "example"
  ]
}

Some other things to note:

  • The metadata specifies the ID that's added to each Thng, using the serial_id identifier name, and other static data to be included in each Thng.
  • Each Thng is linked to the product Blue T-shirt with identifier pid with value 38497. This identifier must correspond to the identifiers of a product in the same account.
  • The purchase order is included to link the Thngs created to the order for their creation.

In this case all the Thngs have the same redirection URL, but templating the shortId alets the destination application to present a different experience for each unique Thng by reading the query string.

Ensure the product exists and has the correct pid identifier. Any client-specific identifier name can be used. Here's an example:

curl -i -H Content-Type:application/json \
  -H Authorization:$OPERATOR_API_KEY \
  -X POST https://api.evrythng.com/products \
  -d '{
  "name": "Blue T-shirt",
  "identifiers": {
    "pid": "38497"
  }
}'
evrythng products create '{
  "name": "Blue T-shirt",
  "identifiers": {
    "pid": "38497"
  }
}'

Create the ADI order using the product's identifier, purchase order ID, and the list of IDs for each Thng. The Thng's serializing identifierKey can be any valid string.

curl -i -H Content-Type:application/json \
  -H Authorization:$OPERATOR_API_KEY \
  -X POST https://api.evrythng.com/adis/orders \
  -d '{
  "metadata": {
    "identifierKey": "serial_id",
    "product": "pid:38497",
    "tags": [
      "shipped",
      "boxed"
    ],
    "shortDomain": "tn.gg",
    "defaultRedirectUrl": "https://evrythng.com?id={shortId}"
  },
  "purchaseOrder": "893456798",
  "ids": [
    "3829645",
    "3829646",
    "3829647",
    "3829648",
    "3829649",
    "3829650",
    "3829651",
    "3829652",
    "3829653",
    "3829654"
  ],
  "tags": [
    "example"
  ]
}'
evrythng adi-orders create '{
  "metadata": {
    "identifierKey": "serial_id",
    "product": "pid:38497",
    "tags": [
      "shipped",
      "boxed"
    ],
    "shortDomain": "tn.gg",
    "defaultRedirectUrl": "https://evrythng.com?id={shortId}"
  },
  "purchaseOrder": "893456798",
  "ids": [
    "3829645",
    "3829646",
    "3829647",
    "3829648",
    "3829649",
    "3829650",
    "3829651",
    "3829652",
    "3829653",
    "3829654"
  ],
  "tags": [
    "example"
  ]
}'

The response confirms the details of the order, and includes an id for the ADI order (to enable reads) and the status . The latter enables you to view the progress of large orders.

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

{
  "id": "UNhRqnhkVM87trwRwhQKbaKr",
  "status": {
    "state": "pending",
    "requested": 10,
    "adis": {
      "created": 0,
      "pending": 0,
      "errorsCount": 0
    }
  },
  "metadata": {
    "identifierKey": "serial_id",
    "product": "pid:38497",
    "tags": [
      "shipped",
      "boxed"
    ],
    "shortDomain": "tn.gg",
    "defaultRedirectUrl": "https://evrythng.com?id={shortId}"
  },
  "purchaseOrder": "893456798",
  "tags": [
    "example"
  ]
}

Thngs with IDs from a CSV File

IDs of individual product items to be imported to the EVRYTHNG Platform are often provided in a CSV file, such as the example shown below. This is especially common if the IDs are sourced from an external system or partner.

id,name,destination,pid,color
6587565785,Blue T-shirt,ES,38497,red
7875675860,Blue T-shirt,ES,38497,red
8687567547,Blue T-shirt,ES,38497,red
6758675779,Blue T-shirt,ES,38497,red
7765463764,Blue T-shirt,ES,38497,red
7887566786,Blue T-shirt,ES,38497,red

The solution to this case is to prepare the list of IDs separately in JSON format. This solution works well when using the evrythng.js SDK to create the order, as demonstrated below in a Node.js script:

const evrythng = require('evrythng');
const fs = require('fs');
const neatCsv = require('neat-csv');

const [csvPath] = process.argv.slice(2);
const { OPERATOR_API_KEY } = process.env;

/**
 * The main function. Reads the CSV file and creates an ADI order
 */
const main = async () => {
  // Read the CSV file
  const records = await neatCsv(fs.readFileSync(csvPath, 'utf8'));

  // Assemble the order using the IDs column mapped to list
  const payload = {
    metadata: {
      product: 'gs1:01:00789968000023',
      identifierKey: 'gs1:21',
      tags: ['example'],
      shortDomain: 'tn.gg',
      defaultRedirectUrl: 'https://evrythng.com?id={shortId}'
    },
    ids: records.map(p => p.id),
    purchaseOrder: '893456798',
    tags: ['example'],
  };

  // Create the ADI order and show the ID
  const operator = new evrythng.Operator(OPERATOR_API_KEY);
  const res = await operator.adiOrder().create(payload);
  console.log(`Created ADI order: ${res.id}`);
};

main();

Run the script on the example file ids.csv:

# Dependencies
npm i --save evrythng neat-csv

# Order the IDs using an ADI order
node orderIds.js ./ids.csv
Created ADI order: UNYa7edqeMs7tNwwwhH8En4k

As before, this ID can be used to retrieve the status of the order and track its progress:

curl -i -H Authorization:$OPERATOR_API_KEY \
  -X GET https://api.evrythng.com/adis/orders/UNYa7edqeMs7tNwwwhH8En4k
evrythng adi-orders UNYa7edqeMs7tNwwwhH8En4k read

After a short time, the response shows the order is complete:

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

{
  "id": "UNYa7edqeMs7tNwwwhH8En4k",
  "status": {
    "state": "completed",
    "requested": 10,
    "adis": {
      "created": 10,
      "pending": 0,
      "errorsCount": 0
    }
  },
  "metadata": {
    "identifierKey": "serial_id",
    "product": "pid:38497",
    "tags": [
      "example"
    ],
    "shortDomain": "tn.gg",
    "defaultRedirectUrl": "https://evrythng.com?id={shortId}"
  },
  "purchaseOrder": "893456798",
  "tags": [
    "example"
  ]
}

Generate Thngs with a GS1 Digital Link

Thngs and products can be associated with a GS1 Digital Link, which includes their GS1 standard GTIN and serial numbers, for example. A common use case of the ADI Orders API is to generate Thngs and that include this information. By adding the redirection short domain and URL template, the GS1 Digital Link integration is enabled for the generated Thngs in one step.

To recap the GS1 Digital Link integration documentation:

  • The product identifiers includes gs1:01 for the GTIN.
  • The Thng identifiers includes gs1:21 for the serial number.
  • The Thng refers to the product as its product property, representing unique instances of the product SKU.
  • The Thng must have a redirection set up, to provide a destination for users.

After these are in place, you can refer to the Thng and product through a GS1 Digital Link URL. In this scenario, the GTIN is the 14-character string 00789968000023, and the Thng serial numbers increase from 5009645 through 5009654 for 10 Thngs total (though this is often many times larger).

The first step is to create (or update) the product, and ensure the GTIN is set in identifiers:

curl -i -H Content-Type:application/json \
  -H Authorization:$OPERATOR_API_KEY \
  -X POST https://api.evrythng.com/products \
  -d '{
  "name": "Blue T-shirt",
  "identifiers": {
    "gs1:01": "00789968000023"
  }
}'
evrythng products create '{
  "name": "Blue T-shirt",
  "identifiers": {
    "gs1:01": "00789968000023"
  }
}'

The next step is to create the Thngs with the ADI Orders API. This creates each Thng using the metadata as the template, referring to the product with the GTIN identifier, and specifying the IDs with an identifierKey of gs1:21 and individual IDs between 5009645 and 5009654:

curl -i -H Content-Type:application/json \
  -H Authorization:$OPERATOR_API_KEY \
  -X POST https://api.evrythng.com/adis/orders \
  -d '{
  "metadata": {
    "identifierKey": "gs1:21",
    "product": "gs1:01:00789968000023",
    "tags": [
      "example"
    ],
    "shortDomain": "tn.gg",
    "defaultRedirectUrl": "https://evrythng.com?id={shortId}"
  },
  "purchaseOrder": "893456798",
  "ids": [
    "5009645",
    "5009646",
    "5009647",
    "5009648",
    "5009649",
    "5009650",
    "5009651",
    "5009652",
    "5009653",
    "5009654"
  ],
  "tags": [
    "example"
  ]
}'
# Create with payload string
evrythng adi-orders create '{
  "metadata": {
    "identifierKey": "gs1:21",
    "product": "gs1:01:00789968000023",
    "tags": [
      "example"
    ],
    "shortDomain": "tn.gg",
    "defaultRedirectUrl": "https://evrythng.com?id={shortId}"
  },
  "purchaseOrder": "893456798",
  "ids": [
    "5009645",
    "5009646",
    "5009647",
    "5009648",
    "5009649",
    "5009650",
    "5009651",
    "5009652",
    "5009653",
    "5009654"
  ],
  "tags": [
    "example"
  ]
}'

After this process has completed, you should be able to obtain a redirected experience from any of the Thngs created via their GS1 Digital Link. For example, for a Thng with a identifiers.gs1:21 of 5009646 associated with a product with a identifiers.gs1:01 of 00789968000023 will have the following GS1 Digital Link made available by the EVRYTHNG Platform:

https://abcde.tn.gg/01/00789968000023/21/5009646

where abcde is the GS1 domain for the account concerned.

Test this easily with the cURL command:

curl -i https://abcde.tn.gg/01/00789968000023/21/5009646

The result contains the desired redirection URL set as the location header:

HTTP/1.1 307 Temporary Redirect
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Link, Location, X-Result-Count, X-Calculation-Date
date: Tue, 13 Nov 2018 15:31:42 GMT
link: <https://id.gs1.org/01/00789968000023/21/5009646>; rel="canonical"
location: https://evrythng.com?id=fyzqDStf
Strict-Transport-Security: max-age=15552000; includeSubDomains
Content-Length: 0
Connection: keep-alive

This result indicates that the GS1 Digital Link for the Thng is in good working order. You can get a QR code for this link from the EVRYTHNG Dashboard, or encode the full URL into a QR code using your preferred generator.


Conclusion

This section showed three of the most common use cases of the ADI Orders API, but more can be catered for—the metadata for the Thngs and orders include the ability to extend with additional identifiers and customFields.

For detailed information on ADI order creation and the different options available, read the ADI Orders API Reference page.