Date relationships
Use format: "date-time" to require a valid timestamp. Use OPA when timestamps must also relate to one another or to an allowed window.
This example interprets a request for a one-hour booking at 10:00 UTC. State supplies the allowed window, 09:00–17:00 UTC. The rules require the start to precede the end and both to fit that window.
Define the output, window and comparison
Save these files. The schema requires timestamps with timezones. Rego converts them into instants before comparing, so different offsets for the same time behave consistently.
{
"type": "object",
"properties": {
"starts_at": {
"type": "string",
"format": "date-time",
"description": "The requested start, as an RFC 3339 timestamp with a timezone."
},
"ends_at": {
"type": "string",
"format": "date-time",
"description": "The requested end, strictly after starts_at and within the permitted window in state."
}
},
"required": ["starts_at", "ends_at"],
"additionalProperties": false
}
{"window_start": "2026-10-05T09:00:00Z", "window_end": "2026-10-05T17:00:00Z"}
package schedule
default allow := false
allow if {
start := time.parse_rfc3339_ns(input.output.starts_at)
end := time.parse_rfc3339_ns(input.output.ends_at)
earliest := time.parse_rfc3339_ns(input.state.window_start)
latest := time.parse_rfc3339_ns(input.state.window_end)
earliest <= start
start < end
end <= latest
}
Send the request
The model receives the booking request and window. The policy enforces the date relationships:
Before you run this example
Call https://api.blatent.ai from your server. Set your API key in the same terminal where you run the example:
export BLATENT_API_KEY='YOUR_SERVICE_KEY'
Python requires Python 3.10+ and HTTPX:
python -m pip install "httpx>=0.28,<1"
TypeScript requires Node.js 24+ and uses its built-in fetch. The cURL examples require curl and jq.
Save the displayed files and the selected client in one directory. Run the client there with python example.py, node example.ts or bash example.sh. Downloads use the example's name in place of example.
- Python
- TypeScript
- cURL
import json
import os
from pathlib import Path
import httpx
request = {
"input": "Book a one-hour review on October 5, 2026, starting at 10:00 UTC, within the permitted window.",
"policy": {
"engine": "opa",
"entrypoint": "data.schedule.allow",
"modules": {
"schedule.rego": Path("schedule.rego").read_text(encoding="utf-8"),
},
},
"policy_max_retries": 8,
"schema": json.loads(Path("schedule.schema.json").read_text(encoding="utf-8")),
"state": json.loads(Path("schedule.state.json").read_text(encoding="utf-8")),
}
with httpx.Client(
base_url="https://api.blatent.ai",
headers={"Authorization": f"Bearer {os.environ['BLATENT_API_KEY']}"},
timeout=195,
) as client:
response = client.post("/v1/resolve", json=request)
response.raise_for_status()
print(json.dumps(response.json()["output"]))
import { readFileSync } from "node:fs";
const request = {
"input": "Book a one-hour review on October 5, 2026, starting at 10:00 UTC, within the permitted window.",
"policy": {
"engine": "opa",
"entrypoint": "data.schedule.allow",
"modules": {
"schedule.rego": readFileSync("schedule.rego", "utf8"),
},
},
"policy_max_retries": 8,
"schema": JSON.parse(readFileSync("schedule.schema.json", "utf8")),
"state": JSON.parse(readFileSync("schedule.state.json", "utf8")),
};
const response = await fetch(
"https://api.blatent.ai" + "/v1/resolve",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BLATENT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(request),
signal: AbortSignal.timeout(195_000),
},
);
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(JSON.stringify((await response.json()).output));
set -eu
body=$(jq -n --argjson body '{"input":"Book a one-hour review on October 5, 2026, starting at 10:00 UTC, within the permitted window.","policy":{"engine":"opa","entrypoint":"data.schedule.allow","modules":{}},"policy_max_retries":8}' \
--slurpfile f0 'schedule.schema.json' \
--slurpfile f1 'schedule.state.json' \
--rawfile f2 'schedule.rego' \
'$body | setpath(["schema"]; $f0[0]) | setpath(["state"]; $f1[0]) | setpath(["policy","modules","schedule.rego"]; $f2)')
curl --fail-with-body --silent --show-error \
"https://api.blatent.ai/v1/resolve" \
-H "Authorization: Bearer $BLATENT_API_KEY" \
-H 'Content-Type: application/json' \
--data-binary "$body"
Illustrative output: {"starts_at":"2026-10-05T10:00:00Z","ends_at":"2026-10-05T11:00:00Z"}.
| Candidate | Policy result |
|---|---|
| 10:00–11:00 UTC inside the window | Allowed |
| 12:00–13:00 at UTC+02:00, the same instants | Allowed |
| End equals or precedes start | Denied |
| Starts before 09:00 UTC or ends after 17:00 UTC | Denied |
| Unparseable timestamp | Not allowed |
Distinguish interpretation from enforcement
The window includes both endpoints and duration must be positive. The requested 10:00 start and one-hour duration are explained to the model; this particular policy does not independently enforce them. Add comparisons against trusted state values if those must also be mandatory.
A successful response proposes times. It does not reserve a calendar slot. Your application checks current availability before booking. If policy search cannot find a compliant proposal within its budget, the request fails rather than returning an invalid range.
See formats and patterns for individual value constraints and OPA for the policy request fields.