Management APIs / Reactions

Update a data reaction

PATCHhttps://api.spice.ai/v1/projects/{projectId}/reactions/{alertId}

Updates reaction fields supplied in the request. Requires reactions:write and organization membership.

Authorizations

  • AuthorizationstringRequired

    Bearer <token>. Authentication lists the tokens it accepts.

Path parameters

  • projectIdintegerRequired

  • alertIdstring (uuid)Required

Header parameters

  • X-Org-Namestring

    The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but GET /v1/orgs (400 org_assertion_required otherwise).

    • Pattern: ^[A-Za-z0-9._-]{1,255}$

Body

application/jsonRequired

  • namestring

    • Minimum length: 1
    • Maximum length: 100
  • descriptionstring | null

    • Maximum length: 500
  • statusstring

    • Allowed values: active, disabled
  • templateIdstring

  • specobject

  • targetobject

    A notification sink in a create or update request. Cluster monitors, project monitors and data reactions accept the same shape.

    3 options

    One of

    type: emailobject
    • typestringRequired

      • Value: email
    • recipientUserIdsarray of integer

      Organization members to email, by user ID.

      • Maximum items: 50
    • emailsarray of string (email)

      • Maximum items: 20
    type: httpobject
    • typestringRequired

      • Value: http
    • urlstring (uri)Required

      The URL each notification is sent to, using method. Must be https and must resolve to a public address.

      • Minimum length: 1
      • Maximum length: 2048
    • methodstring

      A create that omits it uses POST. An update that omits it keeps the stored method.

      • Allowed values: POST, PUT, PATCH
    • tokenstring

      Bearer token sent with each delivery. Stored encrypted and never returned.

      • Minimum length: 1
      • Maximum length: 512
    type: slackobject
    • typestringRequired

      • Value: slack
    • channelIdstringRequired

      Slack conversation id. The organization must already have Slack connected.

      • Minimum length: 9
      • Maximum length: 32
      • Pattern: ^[CGD][A-Z0-9]{8,31}$
    • channelNamestring

      • Minimum length: 1
      • Maximum length: 80
  • targetsarray of object

    • Minimum items: 1
    • Maximum items: 3
    3 options

    One of

    type: emailobject
    • typestringRequired

      • Value: email
    • recipientUserIdsarray of integer

      Organization members to email, by user ID.

      • Maximum items: 50
    • emailsarray of string (email)

      • Maximum items: 20
    type: httpobject
    • typestringRequired

      • Value: http
    • urlstring (uri)Required

      The URL each notification is sent to, using method. Must be https and must resolve to a public address.

      • Minimum length: 1
      • Maximum length: 2048
    • methodstring

      A create that omits it uses POST. An update that omits it keeps the stored method.

      • Allowed values: POST, PUT, PATCH
    • tokenstring

      Bearer token sent with each delivery. Stored encrypted and never returned.

      • Minimum length: 1
      • Maximum length: 512
    type: slackobject
    • typestringRequired

      • Value: slack
    • channelIdstringRequired

      Slack conversation id. The organization must already have Slack connected.

      • Minimum length: 9
      • Maximum length: 32
      • Pattern: ^[CGD][A-Z0-9]{8,31}$
    • channelNamestring

      • Minimum length: 1
      • Maximum length: 80
  • recipientUserIdsarray of integer

Responses

200Reaction updatedapplication/json

A data reaction, as returned by the list, get, create and update operations. Every property is always present; a nullable one carries null rather than being omitted. Fields not listed here are internal to the platform and are not part of the contract.

  • idstring (uuid)Required

    Identifier of the monitor or reaction. This is the value the get, update and delete operations take.

  • org_idintegerRequired

    Organization that owns the project

  • app_idintegerRequired

    Project the monitor or reaction belongs to

  • created_byinteger | nullRequired

    User who created it, when it was created by a user credential

  • namestringRequired

    Display name, unique case-insensitively among the project's live monitors and data reactions

  • descriptionstring | nullRequired

  • kindstringRequired

    The reactions endpoints only ever return data.

    • Value: data
  • statusstringRequired

    Whether it is evaluating

    • Allowed values: active, disabled
  • template_idstringRequired

    Template it was created from

  • specobjectRequired

    Reaction parameters, normalized for the response: a reaction whose model transform is still held on target is returned with that transform copied into spec.model. Which properties are meaningful is decided by template_id. The create operation's request body lists the properties each template reads.

  • targetobjectRequired

    The primary sink (email, then slack, then http). targets is the full list. An HTTP sink's token is write-only and is never returned.

    3 options

    One of

    type: emailobject
    • typestringRequired

      • Value: email
    • recipientUserIdsarray of integer

    • emailsarray of string (email)

    type: httpobject
    • typestringRequired

      • Value: http
    • urlstring (uri) | ""Required

      The sink's URL. An empty string means the stored sink no longer passes validation. Update the sink to replace it.

    • methodstring

      • Allowed values: POST, PUT, PATCH
    type: slackobject
    • typestringRequired

      • Value: slack
    • channelIdstring | ""Required

      The Slack channel ID. An empty string means the stored sink no longer passes validation. Update the sink to replace it.

    • channelNamestring

      • Minimum length: 1
      • Maximum length: 80
  • targetsarray of objectRequired

    Every configured sink, ordered email, then slack, then http. target is the first of these. An HTTP sink's token is never returned.

    • Minimum items: 1
    • Maximum items: 3
    3 options

    One of

    type: emailobject
    • typestringRequired

      • Value: email
    • recipientUserIdsarray of integer

    • emailsarray of string (email)

    type: httpobject
    • typestringRequired

      • Value: http
    • urlstring (uri) | ""Required

      The sink's URL. An empty string means the stored sink no longer passes validation. Update the sink to replace it.

    • methodstring

      • Allowed values: POST, PUT, PATCH
    type: slackobject
    • typestringRequired

      • Value: slack
    • channelIdstring | ""Required

      The Slack channel ID. An empty string means the stored sink no longer passes validation. Update the sink to replace it.

    • channelNamestring

      • Minimum length: 1
      • Maximum length: 80
  • recipient_user_idsarray of integerRequired

    Organization members emailed when it fires. Empty when there is no email sink, and for an email sink addressed only by emails. When a created email sink named no recipients at all, the API stores the creating user.

  • last_fired_atstring (date-time) | nullRequired

    When it last fired, or null if it never has

  • last_resolved_atstring (date-time) | nullRequired

    When it last resolved, or null if it never has

  • created_atstring (date-time)Required

  • updated_atstring (date-time)Required

400Invalid request, specification, or dataset

401Unauthorized

403Insufficient scope or organization membership

404Project or reaction not found

409Name conflict or concurrent update

413Request body too large

422Project configuration is incomplete

429Another update is in progress for this reaction

500Internal server error

502Drasi update failed

503The project's Drasi data source or lock store is unavailable

curl -X PATCH "https://api.spice.ai/v1/projects/<projectId>/reactions/<alertId>" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "string",
    "description": "string",
    "status": "active",
    "templateId": "string",
    "spec": {},
    "target": {
      "type": "email"
    },
    "targets": [
      {
        "type": "email"
      }
    ],
    "recipientUserIds": [
      0
    ]
  }'
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "org_id": 0,
  "app_id": 0,
  "created_by": 0,
  "name": "string",
  "description": "string",
  "kind": "data",
  "status": "active",
  "template_id": "string",
  "spec": {},
  "target": {
    "type": "email",
    "recipientUserIds": [
      0
    ],
    "emails": [
      "user@example.com"
    ]
  },
  "targets": [
    {
      "type": "email",
      "recipientUserIds": [
        0
      ],
      "emails": [
        "user@example.com"
      ]
    }
  ],
  "recipient_user_ids": [
    0
  ],
  "last_fired_at": "2026-01-01T00:00:00Z",
  "last_resolved_at": "2026-01-01T00:00:00Z",
  "created_at": "2026-01-01T00:00:00Z",
  "updated_at": "2026-01-01T00:00:00Z"
}

application/json

PATCHhttps://api.spice.ai/v1/orgs/{orgId}/projects/{projectId}/reactions/{alertId}

The org is orgId in the path. Updates reaction fields supplied in the request. Requires reactions:write and organization membership.

Authorizations

  • AuthorizationstringRequired

    Bearer <token>. Authentication lists the tokens it accepts.

Path parameters

  • orgIdintegerRequired

    The org id from GET /v1/orgs

    • Minimum: 1
  • projectIdintegerRequired

  • alertIdstring (uuid)Required

Header parameters

  • X-Org-Namestring

    When present, X-Org-Name must name the same org as orgId. Otherwise the request returns org_path_mismatch (400).

    • Pattern: ^[A-Za-z0-9._-]{1,255}$

Body

application/jsonRequired

  • namestring

    • Minimum length: 1
    • Maximum length: 100
  • descriptionstring | null

    • Maximum length: 500
  • statusstring

    • Allowed values: active, disabled
  • templateIdstring

  • specobject

  • targetobject

    A notification sink in a create or update request. Cluster monitors, project monitors and data reactions accept the same shape.

    3 options

    One of

    type: emailobject
    • typestringRequired

      • Value: email
    • recipientUserIdsarray of integer

      Organization members to email, by user ID.

      • Maximum items: 50
    • emailsarray of string (email)

      • Maximum items: 20
    type: httpobject
    • typestringRequired

      • Value: http
    • urlstring (uri)Required

      The URL each notification is sent to, using method. Must be https and must resolve to a public address.

      • Minimum length: 1
      • Maximum length: 2048
    • methodstring

      A create that omits it uses POST. An update that omits it keeps the stored method.

      • Allowed values: POST, PUT, PATCH
    • tokenstring

      Bearer token sent with each delivery. Stored encrypted and never returned.

      • Minimum length: 1
      • Maximum length: 512
    type: slackobject
    • typestringRequired

      • Value: slack
    • channelIdstringRequired

      Slack conversation id. The organization must already have Slack connected.

      • Minimum length: 9
      • Maximum length: 32
      • Pattern: ^[CGD][A-Z0-9]{8,31}$
    • channelNamestring

      • Minimum length: 1
      • Maximum length: 80
  • targetsarray of object

    • Minimum items: 1
    • Maximum items: 3
    3 options

    One of

    type: emailobject
    • typestringRequired

      • Value: email
    • recipientUserIdsarray of integer

      Organization members to email, by user ID.

      • Maximum items: 50
    • emailsarray of string (email)

      • Maximum items: 20
    type: httpobject
    • typestringRequired

      • Value: http
    • urlstring (uri)Required

      The URL each notification is sent to, using method. Must be https and must resolve to a public address.

      • Minimum length: 1
      • Maximum length: 2048
    • methodstring

      A create that omits it uses POST. An update that omits it keeps the stored method.

      • Allowed values: POST, PUT, PATCH
    • tokenstring

      Bearer token sent with each delivery. Stored encrypted and never returned.

      • Minimum length: 1
      • Maximum length: 512
    type: slackobject
    • typestringRequired

      • Value: slack
    • channelIdstringRequired

      Slack conversation id. The organization must already have Slack connected.

      • Minimum length: 9
      • Maximum length: 32
      • Pattern: ^[CGD][A-Z0-9]{8,31}$
    • channelNamestring

      • Minimum length: 1
      • Maximum length: 80
  • recipientUserIdsarray of integer

Responses

200Reaction updatedapplication/json

A data reaction, as returned by the list, get, create and update operations. Every property is always present; a nullable one carries null rather than being omitted. Fields not listed here are internal to the platform and are not part of the contract.

  • idstring (uuid)Required

    Identifier of the monitor or reaction. This is the value the get, update and delete operations take.

  • org_idintegerRequired

    Organization that owns the project

  • app_idintegerRequired

    Project the monitor or reaction belongs to

  • created_byinteger | nullRequired

    User who created it, when it was created by a user credential

  • namestringRequired

    Display name, unique case-insensitively among the project's live monitors and data reactions

  • descriptionstring | nullRequired

  • kindstringRequired

    The reactions endpoints only ever return data.

    • Value: data
  • statusstringRequired

    Whether it is evaluating

    • Allowed values: active, disabled
  • template_idstringRequired

    Template it was created from

  • specobjectRequired

    Reaction parameters, normalized for the response: a reaction whose model transform is still held on target is returned with that transform copied into spec.model. Which properties are meaningful is decided by template_id. The create operation's request body lists the properties each template reads.

  • targetobjectRequired

    The primary sink (email, then slack, then http). targets is the full list. An HTTP sink's token is write-only and is never returned.

    3 options

    One of

    type: emailobject
    • typestringRequired

      • Value: email
    • recipientUserIdsarray of integer

    • emailsarray of string (email)

    type: httpobject
    • typestringRequired

      • Value: http
    • urlstring (uri) | ""Required

      The sink's URL. An empty string means the stored sink no longer passes validation. Update the sink to replace it.

    • methodstring

      • Allowed values: POST, PUT, PATCH
    type: slackobject
    • typestringRequired

      • Value: slack
    • channelIdstring | ""Required

      The Slack channel ID. An empty string means the stored sink no longer passes validation. Update the sink to replace it.

    • channelNamestring

      • Minimum length: 1
      • Maximum length: 80
  • targetsarray of objectRequired

    Every configured sink, ordered email, then slack, then http. target is the first of these. An HTTP sink's token is never returned.

    • Minimum items: 1
    • Maximum items: 3
    3 options

    One of

    type: emailobject
    • typestringRequired

      • Value: email
    • recipientUserIdsarray of integer

    • emailsarray of string (email)

    type: httpobject
    • typestringRequired

      • Value: http
    • urlstring (uri) | ""Required

      The sink's URL. An empty string means the stored sink no longer passes validation. Update the sink to replace it.

    • methodstring

      • Allowed values: POST, PUT, PATCH
    type: slackobject
    • typestringRequired

      • Value: slack
    • channelIdstring | ""Required

      The Slack channel ID. An empty string means the stored sink no longer passes validation. Update the sink to replace it.

    • channelNamestring

      • Minimum length: 1
      • Maximum length: 80
  • recipient_user_idsarray of integerRequired

    Organization members emailed when it fires. Empty when there is no email sink, and for an email sink addressed only by emails. When a created email sink named no recipients at all, the API stores the creating user.

  • last_fired_atstring (date-time) | nullRequired

    When it last fired, or null if it never has

  • last_resolved_atstring (date-time) | nullRequired

    When it last resolved, or null if it never has

  • created_atstring (date-time)Required

  • updated_atstring (date-time)Required

400Bad Request

Invalid request, specification, or dataset. orgId is not a valid org id (invalid_org_id), or X-Org-Name does not name that org (org_path_mismatch).

401Unauthorized

403Forbidden

Insufficient scope or organization membership. The caller is not a member of the org (org_forbidden). A machine credential named a different org (org_assertion_mismatch). The org is deleted (org_deleted).

404Project or reaction not found

409Name conflict or concurrent update

413Request body too large

422Project configuration is incomplete

429Another update is in progress for this reaction

500Internal server error

502Drasi update failed

503The project's Drasi data source or lock store is unavailable

curl -X PATCH "https://api.spice.ai/v1/orgs/<orgId>/projects/<projectId>/reactions/<alertId>" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "string",
    "description": "string",
    "status": "active",
    "templateId": "string",
    "spec": {},
    "target": {
      "type": "email"
    },
    "targets": [
      {
        "type": "email"
      }
    ],
    "recipientUserIds": [
      0
    ]
  }'
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "org_id": 0,
  "app_id": 0,
  "created_by": 0,
  "name": "string",
  "description": "string",
  "kind": "data",
  "status": "active",
  "template_id": "string",
  "spec": {},
  "target": {
    "type": "email",
    "recipientUserIds": [
      0
    ],
    "emails": [
      "user@example.com"
    ]
  },
  "targets": [
    {
      "type": "email",
      "recipientUserIds": [
        0
      ],
      "emails": [
        "user@example.com"
      ]
    }
  ],
  "recipient_user_ids": [
    0
  ],
  "last_fired_at": "2026-01-01T00:00:00Z",
  "last_resolved_at": "2026-01-01T00:00:00Z",
  "created_at": "2026-01-01T00:00:00Z",
  "updated_at": "2026-01-01T00:00:00Z"
}

application/json

PATCHhttps://api.spice.ai/v1/apps/{appId}/reactions/{alertId}Deprecated

Legacy alias of /v1/projects/{projectId}/reactions/{alertId} — projects were previously called apps. Updates reaction fields supplied in the request. Requires reactions:write and organization membership.

Authorizations

  • AuthorizationstringRequired

    Bearer <token>. Authentication lists the tokens it accepts.

Path parameters

  • appIdintegerRequired

  • alertIdstring (uuid)Required

Header parameters

  • X-Org-Namestring

    The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but GET /v1/orgs (400 org_assertion_required otherwise).

    • Pattern: ^[A-Za-z0-9._-]{1,255}$

Body

application/jsonRequired

  • namestring

    • Minimum length: 1
    • Maximum length: 100
  • descriptionstring | null

    • Maximum length: 500
  • statusstring

    • Allowed values: active, disabled
  • templateIdstring

  • specobject

  • targetobject

    A notification sink in a create or update request. Cluster monitors, project monitors and data reactions accept the same shape.

    3 options

    One of

    type: emailobject
    • typestringRequired

      • Value: email
    • recipientUserIdsarray of integer

      Organization members to email, by user ID.

      • Maximum items: 50
    • emailsarray of string (email)

      • Maximum items: 20
    type: httpobject
    • typestringRequired

      • Value: http
    • urlstring (uri)Required

      The URL each notification is sent to, using method. Must be https and must resolve to a public address.

      • Minimum length: 1
      • Maximum length: 2048
    • methodstring

      A create that omits it uses POST. An update that omits it keeps the stored method.

      • Allowed values: POST, PUT, PATCH
    • tokenstring

      Bearer token sent with each delivery. Stored encrypted and never returned.

      • Minimum length: 1
      • Maximum length: 512
    type: slackobject
    • typestringRequired

      • Value: slack
    • channelIdstringRequired

      Slack conversation id. The organization must already have Slack connected.

      • Minimum length: 9
      • Maximum length: 32
      • Pattern: ^[CGD][A-Z0-9]{8,31}$
    • channelNamestring

      • Minimum length: 1
      • Maximum length: 80
  • targetsarray of object

    • Minimum items: 1
    • Maximum items: 3
    3 options

    One of

    type: emailobject
    • typestringRequired

      • Value: email
    • recipientUserIdsarray of integer

      Organization members to email, by user ID.

      • Maximum items: 50
    • emailsarray of string (email)

      • Maximum items: 20
    type: httpobject
    • typestringRequired

      • Value: http
    • urlstring (uri)Required

      The URL each notification is sent to, using method. Must be https and must resolve to a public address.

      • Minimum length: 1
      • Maximum length: 2048
    • methodstring

      A create that omits it uses POST. An update that omits it keeps the stored method.

      • Allowed values: POST, PUT, PATCH
    • tokenstring

      Bearer token sent with each delivery. Stored encrypted and never returned.

      • Minimum length: 1
      • Maximum length: 512
    type: slackobject
    • typestringRequired

      • Value: slack
    • channelIdstringRequired

      Slack conversation id. The organization must already have Slack connected.

      • Minimum length: 9
      • Maximum length: 32
      • Pattern: ^[CGD][A-Z0-9]{8,31}$
    • channelNamestring

      • Minimum length: 1
      • Maximum length: 80
  • recipientUserIdsarray of integer

Responses

200Reaction updatedapplication/json

A data reaction, as returned by the list, get, create and update operations. Every property is always present; a nullable one carries null rather than being omitted. Fields not listed here are internal to the platform and are not part of the contract.

  • idstring (uuid)Required

    Identifier of the monitor or reaction. This is the value the get, update and delete operations take.

  • org_idintegerRequired

    Organization that owns the project

  • app_idintegerRequired

    Project the monitor or reaction belongs to

  • created_byinteger | nullRequired

    User who created it, when it was created by a user credential

  • namestringRequired

    Display name, unique case-insensitively among the project's live monitors and data reactions

  • descriptionstring | nullRequired

  • kindstringRequired

    The reactions endpoints only ever return data.

    • Value: data
  • statusstringRequired

    Whether it is evaluating

    • Allowed values: active, disabled
  • template_idstringRequired

    Template it was created from

  • specobjectRequired

    Reaction parameters, normalized for the response: a reaction whose model transform is still held on target is returned with that transform copied into spec.model. Which properties are meaningful is decided by template_id. The create operation's request body lists the properties each template reads.

  • targetobjectRequired

    The primary sink (email, then slack, then http). targets is the full list. An HTTP sink's token is write-only and is never returned.

    3 options

    One of

    type: emailobject
    • typestringRequired

      • Value: email
    • recipientUserIdsarray of integer

    • emailsarray of string (email)

    type: httpobject
    • typestringRequired

      • Value: http
    • urlstring (uri) | ""Required

      The sink's URL. An empty string means the stored sink no longer passes validation. Update the sink to replace it.

    • methodstring

      • Allowed values: POST, PUT, PATCH
    type: slackobject
    • typestringRequired

      • Value: slack
    • channelIdstring | ""Required

      The Slack channel ID. An empty string means the stored sink no longer passes validation. Update the sink to replace it.

    • channelNamestring

      • Minimum length: 1
      • Maximum length: 80
  • targetsarray of objectRequired

    Every configured sink, ordered email, then slack, then http. target is the first of these. An HTTP sink's token is never returned.

    • Minimum items: 1
    • Maximum items: 3
    3 options

    One of

    type: emailobject
    • typestringRequired

      • Value: email
    • recipientUserIdsarray of integer

    • emailsarray of string (email)

    type: httpobject
    • typestringRequired

      • Value: http
    • urlstring (uri) | ""Required

      The sink's URL. An empty string means the stored sink no longer passes validation. Update the sink to replace it.

    • methodstring

      • Allowed values: POST, PUT, PATCH
    type: slackobject
    • typestringRequired

      • Value: slack
    • channelIdstring | ""Required

      The Slack channel ID. An empty string means the stored sink no longer passes validation. Update the sink to replace it.

    • channelNamestring

      • Minimum length: 1
      • Maximum length: 80
  • recipient_user_idsarray of integerRequired

    Organization members emailed when it fires. Empty when there is no email sink, and for an email sink addressed only by emails. When a created email sink named no recipients at all, the API stores the creating user.

  • last_fired_atstring (date-time) | nullRequired

    When it last fired, or null if it never has

  • last_resolved_atstring (date-time) | nullRequired

    When it last resolved, or null if it never has

  • created_atstring (date-time)Required

  • updated_atstring (date-time)Required

400Invalid request, specification, or dataset

401Unauthorized

403Insufficient scope or organization membership

404Project or reaction not found

409Name conflict or concurrent update

413Request body too large

422Project configuration is incomplete

429Another update is in progress for this reaction

500Internal server error

502Drasi update failed

503The project's Drasi data source or lock store is unavailable

OpenAPIapi.spice.ai/openapi.json

curl -X PATCH "https://api.spice.ai/v1/apps/<appId>/reactions/<alertId>" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "string",
    "description": "string",
    "status": "active",
    "templateId": "string",
    "spec": {},
    "target": {
      "type": "email"
    },
    "targets": [
      {
        "type": "email"
      }
    ],
    "recipientUserIds": [
      0
    ]
  }'
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "org_id": 0,
  "app_id": 0,
  "created_by": 0,
  "name": "string",
  "description": "string",
  "kind": "data",
  "status": "active",
  "template_id": "string",
  "spec": {},
  "target": {
    "type": "email",
    "recipientUserIds": [
      0
    ],
    "emails": [
      "user@example.com"
    ]
  },
  "targets": [
    {
      "type": "email",
      "recipientUserIds": [
        0
      ],
      "emails": [
        "user@example.com"
      ]
    }
  ],
  "recipient_user_ids": [
    0
  ],
  "last_fired_at": "2026-01-01T00:00:00Z",
  "last_resolved_at": "2026-01-01T00:00:00Z",
  "created_at": "2026-01-01T00:00:00Z",
  "updated_at": "2026-01-01T00:00:00Z"
}

application/json