Get subscription activity timeline
const url = 'http://localhost:8080/v1/subscriptions/example/timeline';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url http://localhost:8080/v1/subscriptions/example/timeline \ --header 'Authorization: Bearer <token>'Returns the subscription’s history from the audit log as
display-ready rows, in the order the actions took effect: by
sim_effective_at for actions on a test-clock subscription,
otherwise by timestamp. On a test-clock subscription timestamp
(wall-clock) may therefore not be in ascending order. It holds at most the 100 most recent
entries. truncated is true when older entries were left out.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Responses
Section titled “Responses”Timeline events.
object
object
When the action was recorded (wall-clock time).
The audit action, e.g. create, cancel, subscription.item_updated.
The line’s tone in older words, read by the dashboard’s dot.
The line’s title, for example “Subscription canceled”.
The line’s meta line as text, without the actor (see
actor_name) and without a date at its end, which is in
detail_timestamp. For example “Starter → Pro”.
The date the end of detail refers to, for the client to format, as in “Trial now ends” followed by this date.
The line’s problem.
True when the action affected a subscription on a test clock.
The test clock’s simulated time when the action took effect.
One activity row in the words of the activity line standard
(ADR-128): a title with no values, the amount when the event moves
money, asks for it or cancels money owed, a problem line on failure
and warning rows, the meta line’s parts and the actor, a tone, and
the event’s time on the entity’s calendar. recorded_at is the
real-world time, set only for an entity on a test clock.
object
The row’s stable key: the event’s id on an invoice timeline
row, the audit entry’s id on a subscription timeline row,
dunning: and the event’s id on a dunning run event (the same
key the invoice timeline gives that event), and email: and
the email’s id on a sent email (likewise).
Machine name of the event.
object
The meta line before the actor. Each item is one segment, shown joined by “ · “; a segment’s parts read as one phrase, for example a money part followed by the text “ refunded to card”.
Who did it. person and api_key carry the name (a person’s email
when they have no name), customer says where through via, and
automatic is anything Hardcount did on its own. Absent when no fact
written with the row names one.
object
Neutral: something happened. success: money arrived, or was returned as intended. warning: needs a look, or money will not be collected. failure: an attempt failed.
True when the subscription has more than 100 audit entries, so the earliest events are missing.
Example
{ "events": [ { "source": "audit", "status": "neutral", "line": { "kind": "invoice.voided", "title": "Payment failed", "amount": { "currency": "USD" }, "problem": "Card declined: insufficient funds", "detail": [ [ { "money": { "currency": "USD" }, "link": { "kind": "invoice" } } ] ], "actor": { "kind": "person", "via": "payment_page" }, "tone": "neutral" } } ]}Subscription not found.
object
object
One of invalid_request_error, authentication_error,
rate_limit_error or api_error. Every error the API
answers has this shape, including an unknown path (404,
code route_not_found) and a method the path does not take
(405, code method_not_allowed, with an Allow header).
The few exceptions are listed in docs/api-surface.md.
The request field the error is about. Sent only when the error
names one. A request body may hold only the fields its
operation lists, spelled and cased as listed: any other
field, or one the server sets (such as id), is refused
with 422 and param naming it. An operation with no request body lists no fields: send
no body, {} or null. The Stripe and Postmark webhooks and
the LiteLLM callback take their sender’s body as it comes.
Example
{ "error": { "type": "invalid_request_error" }}