Polling
Polling is the alternative to webhooks for learning that a document is ready. Instead of Tediware pushing a notification to an endpoint you host, your system pulls processing outcomes from a feed on its own schedule. Use it when your platform cannot accept inbound HTTP requests, such as a firewalled or fetch-only system. When you can host an HTTPS endpoint, webhooks are recommended instead.
Polling and webhooks deliver the same outcomes. A feed entry carries only identifiers (resultId, traceGuid), never document content, so your system pulls the full data through the Results and Artifacts API exactly as it would after a webhook.
When to Use Polling
A partner is set to one delivery method or the other on its Configuration card:
- Webhooks: Tediware builds the partner’s inbound, outbound, and error webhooks and pushes to them. Recommended when your system can receive HTTPS requests.
- Polling: Tediware builds none of those webhooks. Your system pulls the partner’s inbound documents, outbound confirmations, and errors from the feed.
The feed is populated for every partner regardless of delivery method, so a partner on webhooks can also be polled, for reconciliation or as a backstop. Changing a partner’s delivery method rebuilds its inbound and outbound flows.
The Feed Endpoint
GET /platform/feed_entries
Authorization: Key <your-key>
The feed is an append-only stream of every deliverable document and error across your partners, ordered oldest first. Authenticate with an API key created on the API Keys page. The feed returns only your organization’s entries. Sandbox keys cannot read the feed; use a standard key.
Query Parameters
All parameters are optional. Without any, you get the oldest unread page of the whole feed.
partner: a partner key to filter by. An unknown key returns an empty page rather than an error.direction:inboundoroutbound.status:successorerror.since: an ISO 8601 timestamp. Returns entries created at or after it. An invalid timestamp returns400.cursor: an opaque high-water mark from a previous page’snextCursor. Advances past everything already returned.limit: page size, default50, capped at100.
Response
{
"feedEntries": [
{
"id": "8f1d3c2a-...",
"direction": "inbound",
"status": "success",
"createdAt": "2026-06-08T14:22:33.482190Z",
"partnerKey": "ACME",
"traceGuid": "5ab72145-4a4b-40f6-95de-e2579f163f79",
"resultId": "4c2021f8-8310-4628-80f9-b578d4d68e11",
"detail": { "...": "..." }
}
],
"pagination": {
"hasMore": true,
"nextCursor": "MjAyNi0wNi0wOFQxNDoyMjozMy40ODIxOTBafDhmMWQzYzJh"
}
}
Each entry contains:
id: the feed entry’s own identifier.direction:inboundoroutbound.status:successorerror.createdAt: when the entry was written, ISO 8601 UTC with microseconds.partnerKey: the key of the partner this document belongs to.traceGuid: the trace identifier linking all results from the same processing run.resultId: the processing result. Use it withGET /platform/results/:idto retrieve the full result and its artifacts.detail: the result embedded inline, including the artifact ids and any error detail, so the entry is self-sufficient. Download document bytes withGET /platform/artifacts/:id.
The pagination block contains hasMore (whether more entries are waiting beyond this page) and nextCursor (the cursor to pass on your next request).
Cursor Pagination
The feed is a forward-only stream you advance with a cursor:
- Make the first request with no
cursorto start from the beginning, or withsinceto start from a point in time. - Process the returned entries and save
pagination.nextCursor. - Pass that value back as
cursoron the next request to continue past what you already received. - While
pagination.hasMoreistrue, request the next page immediately, until it isfalse. - When
hasMoreisfalse, wait your chosen interval, then poll again with the saved cursor.
Because the cursor is a high-water mark over (createdAt, id), an advancing poller never re-scans entries it has already seen. Persist the latest nextCursor so a restart resumes where it left off.
The Safety Lag
The newest entries are withheld from the feed for about 2 seconds before they become visible. This safety lag guarantees that an entry which commits slightly out of timestamp order can never be skipped by an advancing cursor, which makes polling lossless.
The practical consequence: a document you just processed may not appear for a moment. This is expected and is not a lost delivery; it will be on the next poll. Polling faster than every couple of seconds gains nothing, since anything newer than the lag window is withheld and those requests mostly return empty pages.
Choosing a Polling Interval
Pick an idle interval that matches how quickly you need documents. Anything from a few seconds to several minutes is reasonable, and most integrations are comfortable polling every minute or two. End-to-end latency is roughly your interval plus the 2-second safety lag. Whenever a response carries hasMore: true, drain the backlog with back-to-back requests rather than waiting out the interval between pages.
Handling Errors in the Feed
Errors are recorded per processing attempt, so a document that is retried can produce more than one error entry, each sharing the same traceGuid. If you want one error per document, deduplicate on traceGuid. Fetch the result behind an error entry with GET /platform/results/:id to read its errorMessage.
Rate Limits
The feed draws on the same per-key read budget as the rest of the Platform read API: 240 requests per minute. That budget is shared with result and artifact downloads, so the usual way to exceed it is a burst of artifact downloads after draining a large page, not the polling itself. When you exceed it, the API responds with 429 and a Retry-After header; wait that many seconds before retrying. See the Errors page for the full rate-limit response.
In-App Discovery
For a partner set to Polling, Tediware shows a poll card on the partner page (scoped to the partner) and on each flow page (scoped to the partner and that flow’s direction). Each card has a ready-to-copy curl command with the partner key already filled in, plus a link to create an API key. It is the fastest way to get the exact call for a partner.
Troubleshooting
- The feed is empty: confirm the partner has processed at least one document, that you are using a standard (not sandbox) API key, and that your
partner,direction, orstatusfilters are not excluding everything. - A just-processed document is missing: this is the safety lag. Wait a couple of seconds and poll again.
- The same error appears more than once: errors are per attempt. Deduplicate on
traceGuid. - You keep seeing entries you already processed: you are not passing
nextCursorback ascursor, or you are not persisting it across restarts. 429responses: you are exceeding the shared 240 requests per minute read budget, most often from artifact-download bursts. Back off for theRetry-Afterinterval and spread downloads out.