Skip to main content

Signed callbacks and receiver acknowledgement

Section ID: Guide/je6sdm1op6#overview

A scheduler callback carries the configured body and a signed identity token. Receivers verify the claims, bind accepted work to the registered payload and deduplicate retries.

Callback envelope​

Section ID: Guide/je6sdm1op6#callback-envelope

The body is exactly the payload you configured — there is no envelope wrapping it. Identity does not travel in plaintext headers: there are no X-Tenant-Id or X-Schedule-Id headers to read. The scheduler's identity and firing claims are inside the signed token. The signature authenticates the token claims. It does not automatically bind the raw HTTP body; validate the payload against the schedule registered in your system before accepting work.

Signing keys and claim verification​

Section ID: Guide/je6sdm1op6#signing-keys

Token or key propertyReceiver behavior
Signing algorithmRequire RS256.
kid headerSelect the matching public key from the deployment's JWKS.
Key rotationRefresh the key set as needed; do not pin one key permanently.
JWKS cachingHonor Cache-Control: max-age=300 rather than fetching keys for every callback.

Verification uses public keys. The receiver needs no shared secret or private signing key.

Signed claims​

Section ID: Guide/je6sdm1op6#claims

Illustrative scheduled callback JWT claims.

  • iss: text https://api.travila.ai.
  • sub: text <the schedule owner>.
  • aud: text your-host.example.com/your/endpoint.
  • iat: number 1754500000.
  • exp: number 1754500300.
  • jti: text sched:sched_abc123:1754500000000.
  • trigger: text scheduled.
  • schedule_id: text sched_abc123.
  • tenant_id: text your-tenant.
  • project_id: text default.
ClaimCheck
issMust equal https://api.travila.ai
audMust match the expected normalized host + path
exp / iatRequire both; reject expired tokens, implausible future issuance and lifetimes outside your allowed window
jtiRequired non-empty firing identity; deduplicate within verified scope
triggerscheduled for a scheduler dispatch
schedule_idRequired schedule identity; match your registered schedule
tenant_id, project_id, subRequired scope and owner; compare with the schedule you accept

An act.sub claim appears when the dispatch acts on behalf of another subject.

Configure the issuer and JWKS endpoint for the deployment you use. Do not accept an old issuer or alternate hostname merely because it once served the platform. Treat issuer changes as a deliberate trust-configuration migration.

Audience normalization​

Section ID: Guide/je6sdm1op6#audience

aud is your target URL reduced to host + path — no scheme, no query string, and the scheme's default port dropped. A target of https://api.example.com/hooks/daily-digest produces:

JWT audience illustration.

  • api.example.com/hooks/daily-digest

Verify against the value you expect rather than accepting any audience. This is what stops a token minted for one of your endpoints being replayed against another.

Retry identity and body binding​

Section ID: Guide/je6sdm1op6#replay

Retries of one firing reuse jti = sched:<schedule_id>:<scheduled_time_unix_ms>. The Idempotency-Key header is a convenience copy; use the verified claim for authority and reject a mismatched header.

Bind the acceptance record to the verified issuer, tenant, project, owner, schedule, audience and firing ID, and to a canonical payload digest. Retain it longer than the complete retry/replay window configured for your deployment. A signed token alone does not prove that someone holding it has left the request body unchanged. Compare the body with the schedule configuration saved in your application; the current token does not supply a signed body digest.

Receiver acknowledgement​

Section ID: Guide/je6sdm1op6#acknowledgement

Receiver outcomeScheduler behavior for that firing
HTTP status below 400Records successful delivery; this does not establish completion of downstream work.
408, 425, 429, 5xx, or a network failureRecords failure and retries within the configured attempt limit.
Other 4xxRecords failure and stops retrying that firing.

A later scheduled firing remains independent of the previous delivery outcome. Consecutive failures can auto-pause the schedule.

Respond promptly after durable acceptance and process slow business work out of band. A delivery acknowledgement records receiver acceptance, not completion of the business action.

Agent callback verification​

Section ID: Guide/je6sdm1op6#agent-callback

Scheduled-agent callbacks use the same signed claims, audience normalization and firing identity as other scheduled callbacks.

Verification stepRequired result
Verify the tokenTrusted deployment issuer, valid signature and acceptable issuance/expiry window.
Match the registrationExpected audience, tenant, project, owner and schedule.
Check the payloadBody agrees with the trusted schedule registration; the JWT does not contain a signed body digest.
Accept onceAtomically store the scoped firing identity and payload digest with a pending work item.

Use the complete receiver algorithm before starting the agent.

Scheduled agent completion​

Section ID: Guide/je6sdm1op6#agent-outcome

Interpret the generation result using the canonical conversation outcome contract. Only a completed result permits consuming its completed output; unsuccessful and nonterminal responses can omit messages. A scheduler delivery acknowledgement does not establish agent completion.

Result webhook subscription​

Section ID: Guide/je6sdm1op6#result-webhook

Tip: One subscription per endpoint

The current platform permits one live subscription per endpoint; a second is rejected with ALREADY_EXISTS. Separate endpoints with overlapping filters can receive the same event, so deduplicate shared business effects across those receivers. See Endpoints and subscriptions for changes and cutover guidance.

Document ID: Guide/je6sdm1op6