Torizon API - How metadata works in the /updates

Hi,

I’m trying to improve our update system, and for that would need to send the information to force an update or not to the fleet/device. The docs says : “It is also possible to add custom metadata or a custom download URI when creating the update.

So I’m trying to use that custom metadata to force or not the update. However, the API isn’t responding how i thought it would, and it looks like the “metadata” attribute makes the request go 400 :

curl --location 'https://app.torizon.io/api/v2beta/updates' \
--header 'Content-Type: application/json' \
--header 'Authorization: ••••••' \
--data '{
  "packageIds": [
    "my-package-id"
  ],
  "devices": [
    "my-device-id"
  ],
  "custom": {
    "my-package-id": {
      "uri": "https://example.com/files/foo-1.0.yaml",
      "metadata": "force"
    }
  }
}'

This results in a bad request returning :

{
    "msg": "Error In Upstream Endpoint",
    "description": null,
    "code": "bad_update_request",
    "cause": [
        {
            "reasons": [
                "MissingField"
            ],
            "errorCode": "bad_update_request"
        }
    ],
    "errorId": "xxx"
}

However, it works if we don’t put the metadata field.
Note that I tried using either device or fleet or even the /updates/fleet endpoint which return the same.
I don’t need a custom uri as well, so I’m wondering how to use this custom field correctly for my use ? Is it possible to just send the custom metadata string I need on updates ?

Best regards,

Hi, I’m the Toradex AI Assistant.

I might make mistakes or occasionally get you wrong. Our support team will step in if needed.


Understanding Custom Metadata in Torizon OTA Updates

Based on the API documentation, the issue you’re experiencing is related to the structure of the metadata field within the custom object.

The Problem

According to the API schema(1), the metadata field cannot be a simple string like "force". The documentation shows that metadata should be null or a structured object, not a plain string value.

Correct Structure

Looking at the API documentation example(1), the proper structure for the custom field is:

{
  "custom": {
    "property1": {
      "metadata": null,
      "uri": "http://example.com"
    },
    "property2": {
      "metadata": null,
      "uri": "http://example.com"
    }
  }
}

(1)

Solution

To use custom metadata correctly for your use case, you have a few options:

  1. Set metadata to null if you don’t need it:
{
  "custom": {
    "my-package-id": {
      "uri": "https://example.com/files/foo-1.0.yaml",
      "metadata": null
    }
  }
}
  1. Omit the metadata field entirely if you only need the custom URI - this is why your request works without the metadata field.

  2. Use a structured object for metadata instead of a string (though the exact schema for the metadata object isn’t detailed in the available documentation).

Unfortunately, the available documentation doesn’t provide detailed examples of what structure the metadata object should have when it’s not null. You may need to experiment with a JSON object structure or contact Toradex support for specific guidance on the metadata schema.

Could you clarify which version of Torizon OS you’re running and which hardware platform you’re using? This might help provide more specific guidance.

Best regards,
Toradex AI Assistant.



Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

Unfortunately, the problem is that I want to use the metadata field and not the uri one, and it doesn’t seem to be either working or specified in the doc how to use it.

I’m using Torizon OS 7.5.0 and verdin-IMX8MP, but it seems that the issue there is more related to the use of the torizon cloud API then my devices.

Based on the available documentation, I need to clarify that the specific structure and usage of the metadata field in the /updates API endpoint is not fully detailed in the sources provided.

What the Documentation Shows

The API documentation(1) shows the schema for the custom metadata field as:

{
  "custom": {
    "property1": {
      "metadata": null,
      "uri": "http://example.com"
    },
    "property2": {
      "metadata": null,
      "uri": "http://example.com"
    }
  }
}

(1)

However, the documentation only shows metadata: null in the examples and doesn’t provide details on what structure the metadata object should have when it’s not null.

The Issue

The “MissingField” error you’re receiving when trying to use "metadata": "force" suggests that:

  1. The metadata field cannot be a simple string value
  2. It likely expects a specific object structure that isn’t documented in the available API reference

Current Limitation

Unfortunately, the available Toradex documentation does not specify:

  • What the expected schema/structure is for the metadata field when it’s not null
  • How this metadata is consumed or processed by Aktualizr on the device
  • Examples of valid metadata object structures

The documentation for Aktualizr(2) and the subsystem updates feature(3) mention custom metadata in general terms but don’t provide the specific API schema details you need.

Recommendation

Since the metadata field structure isn’t documented in the available sources, I recommend reaching out to Toradex support directly with your specific use case (forcing updates via metadata). They should be able to provide:

  • The correct JSON schema for the metadata field
  • How this metadata is accessible on the device side
  • Whether this approach supports your “force update” requirement

You may find relevant discussions on the Toradex Community by searching for “custom metadata updates”.

Best regards,
Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

Ok, I actually understood it wrong, metedata isn’t a specific field, it just means we can use custom and than change one of the fields of the package schema, in my case i just need one field, I’ve using the packages field doesn’t make errors anymore.

curl --location 'https://app.torizon.io/api/v2beta/updates' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer token' \
--data '{
  "packageIds": [
    "my-package-id"
  ],
  "devices": [
    "my-device-id"
  ],
  "custom": {
    "my-package-id": {
      "comment": "force"
    }
  }
}'

However, it looks like the d-bus api doesn’t give those customs info as I thought it would and I therefore cannot use this to differentiate mandatory from optionnal updates.
Might use the version from the package to do it.

Greetings @vlr,

As you discovered the API only lets you customize the custom field of the update metadata. The rest of the metadata fields are managed by our platform as these are critical to update functionality.

Out of curiosity, could you elaborate on your use-case here. I’m not sure I fully understand what you are trying to achieve here with regards to a “forced” vs “optional” update.

Best Regards,
Jeremias

Hey Jeremias,

The problem we have is that we are struggling to keep our fleet up-to-date with the last updates we make, since it is our application system that checks from the d-bus if there is new update and then accept them on start-up of the device or when it sees there is no activity. However, doing so, it happens to disrupt our clients workflow sometimes, like a windows update applying at the worst time, since they, most of the time, only boot up the device at moment they need it critically.

So the idea is to be able to differenciate breaking changes updates that would need to be forced onto the device automatically and optional ones that we can therefore let the user choose to do directly or later.

As said in my previous answer, I went with the approach to put a flag in the version name with our CI when it detects breaking changes commit, and it’s working as intended.

Best regards,
Vincent

Thanks for clarifying your use-case it’s helpful for us to know.

Best Regards,
Jeremias