Reorder resolution rules
Atomically update order_index on a contiguous block of rules in a single transaction. Every rule referenced by short_id must belong to the URL’s organization, otherwise the whole call aborts with 404 and no rules are mutated. Returns the affected rules in their new evaluation order.
Authorizations
Path Parameters
UUID of the organization whose rules are being reordered.
22^[23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}$Body
Body for the bulk reorder endpoint — the list of new (rule, order_index) pairs.
Complete new ordering for a contiguous block of rules. The API applies the changes in a single transaction; any short_id in the list that doesn't belong to the URL's organization aborts the whole reorder with 404 and no rules are mutated.
Response
OK
URL-safe 22-character shortuuid encoding of the row's UUID primary key. Stable across the row's lifetime; suitable for sharing in URLs, log lines, and external SDK clients. Accepted on input as either the shortuuid form or the canonical UUID form (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
22^[23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}$Hierarchy level at which this rule applies. Mirrors apps.resolver.models.ScopeType. Specificity ascends ORGANIZATION → BRAND → PRODUCT → BATCH → SERIAL — the evaluator walks scopes most-specific first, so a rule scoped to a single serial beats a rule scoped to the whole brand.
ORGANIZATION, BRAND, PRODUCT, BATCH, SERIAL Evaluation order within the rule's (scope_type, scope_id) bucket. Lower values are evaluated first; the first matching rule wins. Unique per (scope_type, scope_id, order_index) — duplicates are rejected by the database constraint.
Whether the rule is currently active. Disabled rules are skipped by the evaluator but kept in the listing for easy re-enable.
Where to send the resolution. HOSTED_PAGE renders the Closient product page; CUSTOM_URL 302s to custom_url.
HOSTED_PAGE, CUSTOM_URL Behavior when the URL-health monitor has marked custom_url dead. SKIP_RULE falls through to the next matching rule; FALLBACK_TO_HOSTED short-circuits to the Closient-hosted product page. Live URLs are followed regardless of this setting.
SKIP_RULE, FALLBACK_TO_HOSTED Server-side ISO 8601 timestamp of when the rule was created (UTC).
Server-side ISO 8601 timestamp of the rule's last modification (UTC).
Developer-attached key/value data attached to this object. Up to 50 keys; key max 40 chars, value max 500 chars.
Identifier of the scoped entity. Required when scope_type != 'ORGANIZATION' (organization-wide rules use the implicit organization from the URL). Concrete shape depends on scope_type: GTIN-14 string for PRODUCT (e.g. 00012345678905), brand short_id for BRAND, lot/serial value for BATCH/SERIAL. Stored as a CharField so the same column accepts every variant.
URL-safe 22-character shortuuid encoding of the row's UUID primary key. Stable across the row's lifetime; suitable for sharing in URLs, log lines, and external SDK clients. Accepted on input as either the shortuuid form or the canonical UUID form (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
22^[23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}$URL-safe 22-character shortuuid encoding of the row's UUID primary key. Stable across the row's lifetime; suitable for sharing in URLs, log lines, and external SDK clients. Accepted on input as either the shortuuid form or the canonical UUID form (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
22^[23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}$Inclusive lower bound of the rule's active window — the rule matches when now() >= absolute_start_at. null means no lower bound. Compared in the rule's timezone.
Exclusive upper bound of the rule's active window — the rule matches when now() < absolute_end_at. null means no upper bound. Compared in the rule's timezone.
Annually-recurring start date in MM-DD format (e.g. 11-15). When annual_start_mmdd is later in the year than annual_end_mmdd the window wraps year-end (e.g. 11-15 → 01-05 is mid-November to early January). null means no annual constraint.
5^(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$Annually-recurring end date in MM-DD format (e.g. 01-05). See annual_start_mmdd for wrap-around semantics. null means no annual constraint. Both ends should be set together; setting only one is accepted by the API but ignored by the evaluator.
5^(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$Days the rule may match, using Python's datetime.weekday() convention: 0 = Monday, 6 = Sunday. Duplicates are deduplicated and the result is sorted ascending. null (or empty list) means every day matches. Evaluated in the rule's timezone.
Day-of-week value for ResolutionRule.days_of_week.
Uses the Python datetime.weekday() convention: Monday=0,
Sunday=6. Stored as small integers in the underlying
ArrayField(SmallIntegerField); exposed as a typed enum so the
OpenAPI spec advertises the full valid range (enum: [0..6])
instead of the previous "any int".
0, 1, 2, 3, 4, 5, 6 Inclusive lower bound on time-of-day, HH:MM 24-hour. Rule matches when current_time >= time_of_day_start in the rule's timezone. When start is later than end the window wraps midnight (e.g. 22:00 → 02:00 is the late-night window). null means no lower bound.
Exclusive upper bound on time-of-day, HH:MM 24-hour. Rule matches when current_time < time_of_day_end in the rule's timezone. See time_of_day_start for wrap-around semantics. null means no upper bound.
IANA timezone name used to evaluate every other time-criteria field (annual_*, days_of_week, time_of_day_*, absolute_*). E.g. America/New_York, Europe/Berlin, UTC. Falls back to the organization's OrganizationResolverSettings.routing_timezone when null.
50GS1 Web Vocabulary CURIE that the rule applies to (e.g. gs1:pip for Product Information Page, gs1:hasRecallInformation for recall redirects). When present the rule only matches resolutions for that link type; null matches all link types. See the GS1 Web Vocabulary for the full set of CURIEs.
100Allow list of ISO 3166-1 alpha-2 country codes the rule applies to. Matched against the IP-derived country of the scan request. null or empty list = any country. Case-insensitive.
Allow list of subdivision (state / province / region) names the rule applies to. Matched against the IP-derived region name of the scan request. null or empty list = any region. Case-insensitive.
Allow list of city names the rule applies to. Matched against the IP-derived city name of the scan request. null or empty list = any city. Case-insensitive.
External URL to redirect to. Required when destination_type == 'CUSTOM_URL' (enforced both at the schema level and by a database CHECK constraint). Maximum 2048 characters. Health is monitored out-of-band; see on_custom_url_dead for failure behavior.
2048Optional kebab-case section anchor that deep-links a hosted-page scan to a specific section of the product page (e.g. where-to-buy, ingredients, dscsa-recall-status). When set on a HOSTED_PAGE rule the resolver appends #anchor to the redirect URL so the browser scrolls directly to that section. Must be null whenever destination_type != 'HOSTED_PAGE' — for CUSTOM_URL rules, embed any anchor directly in custom_url. The frontend resolver-config picker is responsible for enumerating the sections available on the resolved product; canonical anchor IDs are defined in apps.products.sections.ProductSection.
64^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$