Signals API

The Signals API gives read access to a fixed sample of output from Qriton Signals. It is meant for evaluating the format and the kind of evidence the service produces. It is not live data and is not a monitoring service; private monitoring with your own sources is arranged by contract.

GET /v1/signals/days

List the days of the sample.

Returns the daily records of the sample period, one item per day, in order of date. Each day gives post counts, the verification of its record and the number of candidate groups that day.

Parameters

NameInTypeDescription
fromquerystringFirst day to include (YYYY-MM-DD).
toquerystringLast day to include (YYYY-MM-DD).
pagequeryintegerPage number, from 1.
page_sizequeryintegerItems per page.

Responses

200A page of days.
400Invalid query. Codes: invalid_parameter, unknown_parameter, invalid_range, request_too_long.
405Method other than GET. Codes: method_not_allowed.
500Unexpected failure. Codes: internal_error.

Example request

curl -X GET "https://api.qriton.com/v1/signals/days" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

{
  "sample": {
    "version": "2026-10.1",
    "period": {
      "from": "2026-10-01",
      "to": "2026-10-31"
    },
    "built_at": "2026-11-14T20:36:50.144Z",
    "digest": "daa2ea63f98e47f0f7dd649f86960185cd8c34343fd5d3e2dedac4060ab690f2"
  },
  "notice": "This is sample data for October 2026 from one platform's public Romanian-language political content. A candidate group is not a finding of coordination: it is a lead that needs review by a person. The accuracy of the monitor has not been measured.",
  "filters": {
    "from": "2026-10-01",
    "to": "2026-10-31"
  },
  "page": 1,
  "page_size": 2,
  "total": 31,
  "total_pages": 16,
  "items": [
    {
      "date": "2026-10-01",
      "record_ref": "RO-TT-2026-10-01-001",
      "record": {
        "status": "verified",
        "seal": "digest_only",
        "verification_report_sha256": "dcdfc4687d9cbd40a10baddac124435bf6144776ad00e35f1fe3251c11f76741"
      },
      "posts": {
        "collected": 197,
        "analysed": 137
      },
      "accounts_with_posts": 38,
      "candidate_groups": 0,
      "record_sha256": "f3006486949a73d6e29a0a203343a2af9c32f8d53a0e5414882af63a16fc20b0"
    },
    {
      "date": "2026-10-02",
      "record_ref": "RO-TT-2026-10-02-001",
      "record": {
        "status": "verified",
        "seal": "digest_only",
        "verification_report_sha256": "7d0f97a0dc59814154925fd8cd298813cff9f4c16afb56b755ffed40138217da"
      },
      "posts": {
        "collected": 164,
        "analysed": 119
      },
      "accounts_with_posts": 38,
      "candidate_groups": 0,
      "record_sha256": "b8cbe827d7eb8e687afb645733ac2441c07690a7135af515613050d9f73e94b2"
    }
  ]
}

GET /v1/signals/days/{date}

Get one day of the sample.

Returns the record of one day of the sample period.

Parameters

NameInTypeDescription
date requiredpathstringThe day (YYYY-MM-DD).

Responses

200The day.
400Malformed date. Codes: invalid_parameter, unknown_parameter.
404No record for the day. Codes: day_not_found, not_found.
405Method other than GET. Codes: method_not_allowed.
500Unexpected failure. Codes: internal_error.

Example request

curl -X GET "https://api.qriton.com/v1/signals/days/{date}" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

{
  "sample": {
    "version": "2026-10.1",
    "period": {
      "from": "2026-10-01",
      "to": "2026-10-31"
    },
    "built_at": "2026-11-14T20:36:50.144Z",
    "digest": "daa2ea63f98e47f0f7dd649f86960185cd8c34343fd5d3e2dedac4060ab690f2"
  },
  "notice": "This is sample data for October 2026 from one platform's public Romanian-language political content. A candidate group is not a finding of coordination: it is a lead that needs review by a person. The accuracy of the monitor has not been measured.",
  "day": {
    "date": "2026-10-01",
    "record_ref": "RO-TT-2026-10-01-001",
    "record": {
      "status": "verified",
      "seal": "digest_only",
      "verification_report_sha256": "dcdfc4687d9cbd40a10baddac124435bf6144776ad00e35f1fe3251c11f76741"
    },
    "posts": {
      "collected": 197,
      "analysed": 137
    },
    "accounts_with_posts": 38,
    "candidate_groups": 0,
    "record_sha256": "f3006486949a73d6e29a0a203343a2af9c32f8d53a0e5414882af63a16fc20b0"
  }
}

GET /v1/signals/groups

List candidate groups.

Returns candidate groups: sets of posts that may show the same clip, formed by the daily comparison of clips, and sets of accounts connected by links in a weekly map. Each group states the basis of its links. A group is a lead for review by a person, not a finding of coordination; no group in the sample was reviewed.

Parameters

NameInTypeDescription
fromquerystringInclude groups whose last member was seen on or after this day.
toquerystringInclude groups whose first member was seen on or before this day.
min_sizequeryintegerMinimum number of members.
basisquerystring: "identical_media", "same_sound_and_duration", "same_duration_within_window", "shared_sound", "shared_hashtag", "co_narrative"Only groups with at least one link of this kind.
kindquerystring: "linked_accounts", "possible_same_clip"Only groups of this kind.
pagequeryintegerPage number, from 1.
page_sizequeryintegerItems per page, at most 100.

Responses

200A page of groups.
400Invalid query. Codes: invalid_parameter, unknown_parameter, invalid_range, request_too_long.
405Method other than GET. Codes: method_not_allowed.
500Unexpected failure. Codes: internal_error.

Example request

curl -X GET "https://api.qriton.com/v1/signals/groups" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

{
  "sample": {
    "version": "2026-10.1",
    "period": {
      "from": "2026-10-01",
      "to": "2026-10-31"
    },
    "built_at": "2026-11-14T20:36:50.144Z",
    "digest": "daa2ea63f98e47f0f7dd649f86960185cd8c34343fd5d3e2dedac4060ab690f2"
  },
  "notice": "This is sample data for October 2026 from one platform's public Romanian-language political content. A candidate group is not a finding of coordination: it is a lead that needs review by a person. The accuracy of the monitor has not been measured.",
  "filters": {
    "from": null,
    "to": null,
    "min_size": 2,
    "basis": "co_narrative",
    "kind": null
  },
  "page": 1,
  "page_size": 1,
  "total": 2,
  "total_pages": 2,
  "items": [
    {
      "id": "grp_9fd129741813397ebc73a165",
      "kind": "linked_accounts",
      "formed_by": "weekly_map",
      "period": {
        "from": "2026-10-19",
        "to": "2026-10-25"
      },
      "first_seen": "2026-10-19",
      "last_seen": "2026-10-25",
      "size": 38,
      "member_type": "account",
      "accounts": 38,
      "posts": 899,
      "cross_account": true,
      "linked_pairs": 193,
      "basis": [
        {
          "code": "co_narrative",
          "label": "The same narrative group in the daily synthesis. Narrative groups are written by an automated language model and were not reviewed by a person.",
          "rule": "model_assigned",
          "strength": null,
          "links": 203
        },
        {
          "code": "same_duration_within_window",
          "label": "Posts with their original sound and the same uncommon length, by different accounts, inside the time window. Length alone can coincide.",
          "rule": "fixed_rule",
          "strength": null,
          "links": 87
        },
        {
          "code": "shared_hashtag",
          "label": "The same rare hashtag.",
          "rule": "fixed_rule",
          "strength": null,
          "links": 54
        },
        {
          "code": "shared_sound",
          "label": "The same sound that is not the original sound of the post.",
          "rule": "fixed_rule",
          "strength": null,
          "links": 28
        }
      ],
      "strength": null,
      "themes": [
        {
          "id": "electoral_party_mobilization",
          "label": "Electoral, candidate, and party mobilization",
          "posts": 311
        },
        {
          "id": "russia_related_messaging",
          "label": "Russia-related state, leader, or national messaging",
          "posts": 219
        },
        {
          "id": "war_military_security",
          "label": "War, military, mobilization, and security",
          "posts": 146
        }
      ],
      "clip": null,
      "review": {
        "status": "not_reviewed",
        "is_finding": false,
        "note": "No person has reviewed this group. It records what the posts or accounts have in common and is not a finding of coordination, common control, payment or intent."
      },
      "evidence": {
        "source_file_sha256": "2c1c4a71df8728ef9c060db0b8d6fd9443100b9eba01c481cad866c75c05d973",
        "members_commitment": "521995cce1ec6d1cb876ab6630b1c54f8895c2061dd498fc0f94c5b2f0675745"
      },
      "record_sha256": "d1abe3ca2dd760b59f994be1502790ee85b4ef77d8cf11dc7fa51f7a9f86d1a3"
    }
  ]
}

GET /v1/signals/groups/{id}

Get one candidate group.

Returns one candidate group with the basis of its links, its review state and the digests for checking it.

Parameters

NameInTypeDescription
id requiredpathstringGroup identifier.

Responses

200The group.
400Malformed identifier. Codes: invalid_parameter, unknown_parameter.
404No such group. Codes: group_not_found, not_found.
405Method other than GET. Codes: method_not_allowed.
500Unexpected failure. Codes: internal_error.

Example request

curl -X GET "https://api.qriton.com/v1/signals/groups/{id}" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

{
  "sample": {
    "version": "2026-10.1",
    "period": {
      "from": "2026-10-01",
      "to": "2026-10-31"
    },
    "built_at": "2026-11-14T20:36:50.144Z",
    "digest": "daa2ea63f98e47f0f7dd649f86960185cd8c34343fd5d3e2dedac4060ab690f2"
  },
  "notice": "This is sample data for October 2026 from one platform's public Romanian-language political content. A candidate group is not a finding of coordination: it is a lead that needs review by a person. The accuracy of the monitor has not been measured.",
  "group": {
    "id": "grp_a60e482fc3cd368880da07fc",
    "kind": "possible_same_clip",
    "formed_by": "daily_clip_comparison",
    "period": {
      "from": "2026-10-16",
      "to": "2026-10-16"
    },
    "comparison_day": "2026-10-16",
    "first_seen": "2026-10-16",
    "last_seen": "2026-10-16",
    "size": 2,
    "member_type": "post",
    "accounts": 2,
    "posts": 2,
    "cross_account": true,
    "linked_pairs": null,
    "basis": [
      {
        "code": "same_sound_and_duration",
        "label": "The same library sound and the same length, within a tolerance, published inside the time window.",
        "rule": "fixed_rule",
        "strength": "probable",
        "links": null
      }
    ],
    "strength": "probable",
    "themes": null,
    "clip": {
      "duration_seconds": [
        285
      ],
      "time_span_hours": 3.16,
      "first_seen_known_for_posts": 2
    },
    "review": {
      "status": "not_reviewed",
      "is_finding": false,
      "note": "No person has reviewed this group. It records what the posts or accounts have in common and is not a finding of coordination, common control, payment or intent."
    },
    "evidence": {
      "source_file_sha256": "5c3532ca98566d44e9658c73121da65cc8e9e4534b20ee33228abbba90a4d686",
      "verification_report_sha256": "ba6dff81f269cbbaddee3ff533c33a642a5397caa0b90167483f041bfc30ed91",
      "members_commitment": "4df9d8c97b3a2af6ebe6062dbfdd9690769006f990dcb6aa592d829efbdcf002"
    },
    "record_sha256": "6d7398e43955f8ea031e8ccbb7c96cb3e2c530a484fe24977014f0cefaff4f4b"
  }
}

GET /v1/signals/sample

Get the metadata of the sample.

Returns the period, the build time and the digest of the sample, what it covers, its totals, the weeks with a weekly map and their themes, and the meaning of every label. The digest is the SHA-256 of the canonical JSON of the sample file without its digest field.

Responses

200The sample metadata.
400A parameter was given. Codes: unknown_parameter.
405Method other than GET. Codes: method_not_allowed.
500Unexpected failure. Codes: internal_error.

Example request

curl -X GET "https://api.qriton.com/v1/signals/sample" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

{
  "sample": {
    "schema_version": "qriton.signals.sample.v1",
    "version": "2026-10.1",
    "period": {
      "from": "2026-10-01",
      "to": "2026-10-31"
    },
    "built_at": "2026-11-14T20:36:50.144Z",
    "digest": "daa2ea63f98e47f0f7dd649f86960185cd8c34343fd5d3e2dedac4060ab690f2",
    "records_as_of": "2026-11-11",
    "digest_algorithm": "sha256",
    "digest_canonicalisation": "JSON with object keys sorted at every level, no whitespace, without the digest field"
  },
  "notice": "This is sample data for October 2026 from one platform's public Romanian-language political content. A candidate group is not a finding of coordination: it is a lead that needs review by a person. The accuracy of the monitor has not been measured.",
  "coverage_statement": [
    "The sample covers 1 October 2026 to 31 October 2026 and does not change. It is not live data.",
    "It was built from outputs that the monitor already publishes: one platform (TikTok), public Romanian-language political content read without logging in, four scheduled runs a day at 00:00, 06:00, 12:00 and 18:00 UTC.",
    "It contains daily counts, candidate groups and service figures. It contains no account names, no links to posts or profiles, no post identifiers and no captions or transcripts.",
    "Candidate groups were formed by fixed rules, with one exception: the narrative-group link is assigned by an automated language model. No group was reviewed by a person, and none is a finding of coordination.",
    "The accuracy of the monitor has not been measured. No figure in the sample is an accuracy, precision or recall figure."
  ],
  "totals": {
    "days": 31,
    "days_with_record": 31,
    "posts_collected": 4497,
    "posts_analysed": 3530,
    "candidate_groups": 5,
    "candidate_groups_by_kind": {
      "possible_same_clip": 3,
      "linked_accounts": 2
    }
  },
  "weeks": [
    {
      "week_start": "2026-10-19",
      "week_end": "2026-10-25",
      "days_in_sample_period": 7,
      "days_with_record": 7,
      "accounts": 45,
      "posts": 913,
      "linked_pairs": 193,
      "account_groups": 1,
      "accounts_without_link": 7,
      "strict_links": {
        "pairs": 50,
        "largest_group_accounts": 27,
        "groups": 1,
        "accounts_linked": 27
      },
      "themes": [
        {
          "id": "electoral_party_mobilization",
          "label": "Electoral, candidate, and party mobilization",
          "posts": 313
        },
        {
          "id": "russia_related_messaging",
          "label": "Russia-related state, leader, or national messaging",
          "posts": 220
        },
        {
          "id": "war_military_security",
          "label": "War, military, mobilization, and security",
          "posts": 148
        },
        {
          "id": "sovereignty_nationalism",
          "label": "Sovereignty, nationalism, and patriotic identity",
          "posts": 120
        },
        {
          "id": "religion_history_identity",
          "label": "Religion, history, and civilizational identity",
          "posts": 116
        },
        {
          "id": "protest_civic_mobilization",
          "label": "Protest and civic mobilization",
          "posts": 107
        },
        {
          "id": "institutional_trust_corruption",
          "label": "Institutional distrust, corruption, and alleged wrongdoing",
          "posts": 95
        },
        {
          "id": "gender_family_social_values",
          "label": "Gender, family, and social-values framing",
          "posts": 57
        }
      ],
      "weekly_map_sha256": "2c1c4a71df8728ef9c060db0b8d6fd9443100b9eba01c481cad866c75c05d973"
    },
    {
      "week_start": "2026-10-26",
      "week_end": "2026-11-01",
      "days_in_sample_period": 6,
      "days_with_record": 6,
      "accounts": 44,
      "posts": 749,
      "linked_pairs": 204,
      "account_groups": 1,
      "accounts_without_link": 7,
      "strict_links": {
        "pairs": 43,
        "largest_group_accounts": 23,
        "groups": 2,
        "accounts_linked": 26
      },
      "themes": [
        {
          "id": "electoral_party_mobilization",
          "label": "Electoral, candidate, and party mobilization",
          "posts": 307
        },
        {
          "id": "russia_related_messaging",
          "label": "Russia-related state, leader, or national messaging",
          "posts": 204
        },
        {
          "id": "sovereignty_nationalism",
          "label": "Sovereignty, nationalism, and patriotic identity",
          "posts": 146
        },
        {
          "id": "protest_civic_mobilization",
          "label": "Protest and civic mobilization",
          "posts": 140
        },
        {
          "id": "war_military_security",
          "label": "War, military, mobilization, and security",
          "posts": 126
        },
        {
          "id": "religion_history_identity",
          "label": "Religion, history, and civilizational identity",
          "posts": 113
        },
        {
          "id": "gender_family_social_values",
          "label": "Gender, family, and social-values framing",
          "posts": 78
        },
        {
          "id": "institutional_trust_corruption",
          "label": "Institutional distrust, corruption, and alleged wrongdoing",
          "posts": 67
        }
      ],
      "weekly_map_sha256": "e667ded2e43d9fd99126d99244978510cb55f292868a5b5d0a58c4214ded5c42"
    }
  ],
  "labels": {
    "basis": {
      "identical_media": {
        "label": "The archived files are byte-identical.",
        "rule": "fixed_rule"
      },
      "same_sound_and_duration": {
        "label": "The same library sound and the same length, within a tolerance, published inside the time window.",
        "rule": "fixed_rule"
      },
      "same_duration_within_window": {
        "label": "Posts with their original sound and the same uncommon length, by different accounts, inside the time window. Length alone