API Overview
Biruni resolves natural-language temporal expressions to precise, timezone-aware ISO 8601 datetimes. It is designed for agent workflows: send the extracted temporal phrase, an anchor date, and an IANA timezone.
https://biruni.devAuth:
Authorization: Bearer BIRUNI_API_KEYEndpoint:
POST /v1/resolve
Quickstart
Create an API key in the dashboard, then send one POST request to resolve a temporal phrase.
curl -X POST https://biruni.dev/v1/resolve \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"expression": "next Monday at 9am",
"reference_date": "2026-04-02",
"timezone": "America/New_York"
}'
POST /v1/resolve
Resolve a temporal phrase into a timezone-aware ISO 8601 datetime. The API is deterministic, ambiguity-aware, and intended to be called by agents during execution.
Request format
| Field | Type | Description | |
|---|---|---|---|
expression |
string |
required |
Send only the temporal phrase, not surrounding prose. Good: next Monday at 3pmBad: Can we meet next Monday at 3pm in the office?
|
reference_date |
string |
required | Anchor date in YYYY-MM-DD format. Usually today's local date. For chained resolution, use
the previously resolved date. |
timezone |
string |
required | IANA timezone identifier. Use full IANA names, not abbreviations. Example:
America/New_York, not EST. |
locale |
string |
optional | BCP 47 locale code. Default: en-US. Only English locales supported. |
options |
object |
optional |
Supports prefer_future (bool, default true) and
business_calendar (string, default
us_federal) for business day calculations.
|
Example request body
{
"expression": "next Monday at 9am",
"reference_date": "2026-04-02",
"timezone": "America/New_York",
"locale": "en-US",
"options": {
"prefer_future": true,
"business_calendar": "us_federal"
}
}
Response format
| Field | Type | Description |
|---|---|---|
status |
string |
"resolved" use resolved directly."ambiguous" inspect alternatives before acting."unresolvable" ask the user to rephrase.
|
resolved |
string | null |
ISO 8601 datetime with UTC offset. Null if unresolvable. |
confidence |
string | null |
"high", "medium", or "low" confidence in the chosen
interpretation. |
interpretation |
string |
Human-readable explanation of how the phrase was interpreted. Useful for audit trails and agent reasoning logs. |
ambiguities |
string[] |
List of ambiguity notes, if any. |
alternatives |
object[] |
Alternative interpretations when status is "ambiguous". Each item includes
resolved and interpretation. |
metadata |
object |
Contains expression_type, timezone, calendar_used, holidays_applied, and processing_time_ms. |
Example response
{
"status": "resolved",
"resolved": "2026-04-06T09:00:00-04:00",
"confidence": "high",
"interpretation": "Next Monday from April 2 is April 6. 9:00 AM in America/New_York.",
"ambiguities": [],
"alternatives": [],
"metadata": {
"expression_type": "weekday",
"timezone": "America/New_York",
"calendar_used": "us_federal",
"holidays_applied": [],
"processing_time_ms": 11.2
}
}
Error codes
All errors return a consistent JSON body:
{ "error": { "code": "ERROR_CODE", "message": "..." } }
| Code | HTTP | Description |
|---|---|---|
INVALID_REQUEST |
400 | Malformed or missing required fields. |
UNAUTHORIZED |
401 | Missing or invalid API key. |
UNRESOLVABLE |
422 | Expression could not be parsed. Ask the user to rephrase. |
RATE_LIMITED |
429 | Per-minute or monthly quota exceeded. Check the Retry-After header. |
INTERNAL_ERROR |
500 | Unexpected server failure. |
429 RATE_LIMITED, wait for the
Retry-After header before retrying.
For AI Agents
Use Biruni whenever your agent needs an exact date or time before taking an action.
Tool definition
Copy the MCP
tool definition below into your agent framework. If your framework uses a
different wrapper key, rename inputSchema to match (e.g.
parameters for OpenAI, input_schema for Anthropic).
{
"name": "biruni_resolve",
"description": "Resolve a natural-language temporal phrase to a timezone-aware ISO 8601 datetime. Send only the temporal phrase, not surrounding prose. If status is ambiguous, inspect alternatives before acting.",
"inputSchema": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "The temporal phrase to resolve, e.g. 'next Tuesday at 10am' or 'in 5 business days'. Extract only the time expression from the user's message."
},
"reference_date": {
"type": "string",
"description": "Anchor date in YYYY-MM-DD format. Usually today's local date. For chained resolution, use the previously resolved date."
},
"timezone": {
"type": "string",
"description": "IANA timezone identifier, e.g. 'America/New_York' or 'Europe/London'. Do not use abbreviations like EST or PST."
},
"options": {
"type": "object",
"description": "Optional resolution overrides.",
"properties": {
"prefer_future": {
"type": "boolean",
"description": "Bias ambiguous expressions toward the next upcoming occurrence."
},
"business_calendar": {
"type": "string",
"description": "Business calendar for business day arithmetic. Use 'us_federal' for the MVP."
}
}
}
},
"required": ["expression", "reference_date", "timezone"]
}
}
Integration guide
Register the tool definition above with your agent framework, then paste the rules below into your agent's system prompt or instruction layer so it knows when and how to call the tool.
Usage rules
Copy into your agent's instructions:
When the user mentions a date, time, or deadline, call biruni_resolve instead of
doing date math yourself.
1. Extract only the temporal phrase from the user's message.
Good: "next Monday at 3pm" Bad: "Can we meet next Monday at 3pm?"
2. Map informal timezone names to IANA identifiers ("Eastern" → America/New_York).
3. Set reference_date to today's local date (YYYY-MM-DD), or the output of a
previous call for chained resolution.
4. If status is "resolved", use the resolved datetime directly.
5. If status is "ambiguous", present the alternatives to the user before acting.
6. If status is "unresolvable", ask the user to rephrase.
7. Never fall back to LLM date arithmetic — retry with a cleaner expression instead.
Authorization: Bearer <BIRUNI_API_KEY> header. Store the
key as an environment variable and inject it when your agent makes the HTTP
call to POST https://biruni.dev/v1/resolve.
Common mistakes
| Mistake | What happens | Fix |
|---|---|---|
Sending the full user message as expression |
Parser fails or returns unresolvable |
Extract only the temporal phrase first |
Using timezone abbreviations (EST, PST) |
Rejected or mapped incorrectly | Use IANA names: America/New_York |
Defaulting to UTC when user implies local time |
Result is correct but in the wrong timezone | Infer and map the user's timezone |
Ignoring status: "ambiguous" |
Silently uses wrong interpretation | Check alternatives and present options |
Not checking metadata.holidays_applied for business-day results |
Deadlines can look surprising around federal holidays | Inspect calendar_used and holidays_applied before overriding the output |
| Falling back to LLM date math when Biruni returns an error | Hallucinated dates, wrong holidays | Retry with a cleaner expression or ask user to rephrase |
Expression types
Common patterns Biruni can resolve. Use these as representative examples, not exhaustive limits.
| Expression | Type | Notes |
|---|---|---|
tomorrow |
Relative day | Resolves to the next calendar day from reference_date. |
in 10 business days |
Business day | Skips weekends and holidays per the selected business calendar. Default: us_federal. |
March 30, 2026 |
Absolute date | Resolves directly in the supplied timezone. |
next Friday at 3pm |
Weekday + time | Finds the next matching weekday and attaches the time. |
first Monday of April |
Ordinal pattern | Uses the year implied by reference_date. |
next Friday on a Friday |
Ambiguous | Returns status: "ambiguous" with alternatives. |
Ambiguous response example
{
"status": "ambiguous",
"resolved": "2026-04-10T00:00:00-04:00",
"confidence": "medium",
"interpretation": "'next Friday' on a Friday — interpreted as next week's Friday.",
"ambiguities": ["'next Friday' on a Friday is ambiguous."],
"alternatives": [
{
"resolved": "2026-04-03T00:00:00-04:00",
"interpretation": "Today (this Friday)"
}
]
}