orb-billing
Version:
The official TypeScript library for the Orb API
369 lines • 18.8 kB
JavaScript
;
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Events = void 0;
const resource_1 = require("../../resource.js");
const BackfillsAPI = __importStar(require("./backfills.js"));
const backfills_1 = require("./backfills.js");
const VolumeAPI = __importStar(require("./volume.js"));
const volume_1 = require("./volume.js");
class Events extends resource_1.APIResource {
constructor() {
super(...arguments);
this.backfills = new BackfillsAPI.Backfills(this._client);
this.volume = new VolumeAPI.Volume(this._client);
}
/**
* This endpoint is used to amend a single usage event with a given `event_id`.
* `event_id` refers to the `idempotency_key` passed in during ingestion. The event
* will maintain its existing `event_id` after the amendment.
*
* This endpoint will mark the existing event as ignored, and Orb will only use the
* new event passed in the body of this request as the source of truth for that
* `event_id`. Note that a single event can be amended any number of times, so the
* same event can be overwritten in subsequent calls to this endpoint. Only a
* single event with a given `event_id` will be considered the source of truth at
* any given time.
*
* This is a powerful and audit-safe mechanism to retroactively update a single
* event in cases where you need to:
*
* - update an event with new metadata as you iterate on your pricing model
* - update an event based on the result of an external API call (e.g. call to a
* payment gateway succeeded or failed)
*
* This amendment API is always audit-safe. The process will still retain the
* original event, though it will be ignored for billing calculations. For auditing
* and data fidelity purposes, Orb never overwrites or permanently deletes ingested
* usage data.
*
* ## Request validation
*
* - The `timestamp` of the new event must match the `timestamp` of the existing
* event already ingested. As with ingestion, all timestamps must be sent in
* ISO8601 format with UTC timezone offset.
* - The `customer_id` or `external_customer_id` of the new event must match the
* `customer_id` or `external_customer_id` of the existing event already
* ingested. Exactly one of `customer_id` and `external_customer_id` should be
* specified, and similar to ingestion, the ID must identify a Customer resource
* within Orb. Unlike ingestion, for event amendment, we strictly enforce that
* the Customer must be in the Orb system, even during the initial integration
* period. We do not allow updating the `Customer` an event is associated with.
* - Orb does not accept an `idempotency_key` with the event in this endpoint,
* since this request is by design idempotent. On retryable errors, you should
* retry the request and assume the amendment operation has not succeeded until
* receipt of a 2xx.
* - The event's `timestamp` must fall within the customer's current subscription's
* billing period, or within the grace period of the customer's current
* subscription's previous billing period.
* - By default, no more than 100 events can be amended for a single customer in a
* 100 day period. For higher volume updates, consider using the
* [event backfill](create-backfill) endpoint.
*/
update(eventId, body, options) {
return this._client.put(`/events/${eventId}`, { body, ...options });
}
/**
* This endpoint is used to deprecate a single usage event with a given `event_id`.
* `event_id` refers to the `idempotency_key` passed in during ingestion.
*
* This endpoint will mark the existing event as ignored. Note that if you attempt
* to re-ingest an event with the same `event_id` as a deprecated event, Orb will
* return an error.
*
* This is a powerful and audit-safe mechanism to retroactively deprecate a single
* event in cases where you need to:
*
* - no longer bill for an event that was improperly reported
* - no longer bill for an event based on the result of an external API call (e.g.
* call to a payment gateway failed and the user should not be billed)
*
* If you want to only change specific properties of an event, but keep the event
* as part of the billing calculation, use the [Amend event](amend-event) endpoint
* instead.
*
* This API is always audit-safe. The process will still retain the deprecated
* event, though it will be ignored for billing calculations. For auditing and data
* fidelity purposes, Orb never overwrites or permanently deletes ingested usage
* data.
*
* ## Request validation
*
* - Orb does not accept an `idempotency_key` with the event in this endpoint,
* since this request is by design idempotent. On retryable errors, you should
* retry the request and assume the deprecation operation has not succeeded until
* receipt of a 2xx.
* - The event's `timestamp` must fall within the customer's current subscription's
* billing period, or within the grace period of the customer's current
* subscription's previous billing period. Orb does not allow deprecating events
* for billing periods that have already invoiced customers.
* - The `customer_id` or the `external_customer_id` of the original event
* ingestion request must identify a Customer resource within Orb, even if this
* event was ingested during the initial integration period. We do not allow
* deprecating events for customers not in the Orb system.
* - By default, no more than 100 events can be deprecated for a single customer in
* a 100 day period. For higher volume updates, consider using the
* [event backfill](create-backfill) endpoint.
*/
deprecate(eventId, options) {
return this._client.put(`/events/${eventId}/deprecate`, options);
}
/**
* Orb's event ingestion model and API is designed around two core principles:
*
* 1. **Data fidelity**: The accuracy of your billing model depends on a robust
* foundation of events. Orb's API protocol encourages usage patterns that
* ensure that your data is consistently complete and correct.
* 2. **Fast integration**: Sending events into Orb requires no tedious setup steps
* or explicit field schema for your event shape, making it instant to start
* streaming in usage in real-time.
*
* ## Event shape
*
* Events are the starting point for all usage calculations in the system, and are
* simple at their core:
*
* ```ts
* {
* // customer_id and external_customer_id are used to
* // attribute usage to a given Customer. Exactly one of these
* // should be specified in a given ingestion event.
*
* // `customer_id` is the Orb generated identifier for the Customer,
* // which is returned from the Create customer API call.
* customer_id: string,
*
* // external_customer_id is an alternate identifier which is associated
* // with a Customer at creation time. This is treated as an alias for
* // customer_id, and is usually set to an identifier native to your system.
* external_customer_id: string,
*
* // A string name identifying the event, usually a usage
* // action. By convention, this should not contain any whitespace.
* event_name: string,
*
* // An ISO 8601 format date with no timezone offset.
* // This should represent the time that usage occurred
* // and is important to attribute usage to a given
* // billing period. See the notes below on determining the timestamp.
* // e.g. 2020-12-09T16:09:53Z
* timestamp: string,
*
* // A unique value, generated by the client, that is
* // used to de-duplicate events.
* // Exactly one event with a given
* // idempotency key will be ingested, which allows for
* // safe request retries.
* idempotency_key: string
*
* // Optional custom metadata to attach to the event.
* // This might include a numeric value used for aggregation,
* // or a string/boolean value used for filtering.
* // The schema of this dictionary need not be pre-declared, and
* // properties can be added at any time.
* properties: {
* [key: string]?: string | number | boolean,
* },
* }
* ```
*
* ## Required fields
*
* Because events streamed to Orb are meant to be as flexible as possible, there
* are only a few required fields in every event.
*
* - We recommend that `idempotency_key` are unique strings that you generated with
* V4 UUIDs, but only require that they uniquely identify an event (i.e. don’t
* collide).
* - The `timestamp` field in the event body will be used to determine which
* billable period a given event falls into. For example, with a monthly billing
* cycle starting from the first of December, Orb will calculate metrics based on
* events that fall into the range
* `12-01 00:00:00 <= timestamp < 01-01 00:00:00`.
*
* ## Logging metadata
*
* Orb allows tagging events with metadata using a flexible properties dictionary.
* Since Orb does not enforce a rigid schema for this field-set, key-value pairs
* can be added dynamically as your events evolve.
*
* This dictionary can be helpful for a wide variety of use cases:
*
* - Numeric properties on events like `compute_time_ms` can later be inputs to our
* flexible query engine to determine usage.
* - Logging a region or cluster with each event can help you provide customers
* more granular visibility into their usage.
* - If you are using matrix pricing and matching a matrix price key with a
* property, you should ensure the value for that property is sent as a string.
*
* We encourage logging this metadata with an eye towards future use cases to
* ensure full coverage for historical data. The datatype of the value in the
* properties dictionary is important for metric creation from an event source.
* Values that you wish to numerically aggregate should be of numeric type in the
* event.
*
* ## Determining event timestamp
*
* For cases where usage is being reported in real time as it is occurring,
* timestamp should correspond to the time that usage occurred.
*
* In cases where usage is reported in aggregate for a historical timeframe at a
* regular interval, we recommend setting the event `timestamp` to the midpoint of
* the interval. As an example, if you have an hourly reporter that sends data once
* an hour for the previous hour of usage, setting the `timestamp` to the half-hour
* mark will ensure that the usage is counted within the correct period.
*
* Note that other time-related fields (e.g. time elapsed) can be added to the
* properties dictionary as necessary.
*
* In cases where usage is reported in aggregate for a historical timeframe, the
* timestamp must be within the grace period set for your account. Events with
* `timestamp < current_time - grace_period` will not be accepted as a valid event,
* and will throw validation errors. Enforcing the grace period enables Orb to
* accurately map usage to the correct billing cycle and ensure that all usage is
* billed for in the corresponding billing period.
*
* In general, Orb does not expect events with future dated timestamps. In cases
* where the timestamp is at least 24 hours ahead of the current time, the event
* will not be accepted as a valid event, and will throw validation errors.
*
* ## Event validation
*
* Orb’s validation ensures that you recognize errors in your events as quickly as
* possible, and the API provides informative error messages to help you fix
* problems quickly.
*
* We validate the following:
*
* - Exactly one of `customer_id` and `external_customer_id` should be specified.
* - If the `customer_id` is specified, the customer in Orb must exist.
* - If the `external_customer_id` is specified, the customer in Orb does not need
* to exist. Events will be attributed to any future customers with the
* `external_customer_id` on subscription creation.
* - `timestamp` must conform to ISO 8601 and represent a timestamp at most 1 hour
* in the future. This timestamp should be sent in UTC timezone (no timezone
* offset).
*
* ## Idempotency and retry semantics
*
* Orb's idempotency guarantees allow you to implement safe retry logic in the
* event of network or machine failures, ensuring data fidelity. Each event in the
* request payload is associated with an idempotency key, and Orb guarantees that a
* single idempotency key will be successfully ingested at most once. Note that
* when Orb encounters events with duplicate idempotency keys and differing event
* bodies in a batch of events, the entire batch will be rejected.
*
* - Successful responses return a 200 HTTP status code. The response contains
* information about previously processed events.
* - Requests that return a `4xx` HTTP status code indicate a payload error and
* contain at least one event with a validation failure. An event with a
* validation failure can be re-sent to the ingestion endpoint (after the payload
* is fixed) with the original idempotency key since that key is not marked as
* processed.
* - Requests that return a `5xx` HTTP status code indicate a server-side failure.
* These requests should be retried in their entirety.
*
* ## API usage and limits
*
* The ingestion API is designed made for real-time streaming ingestion and
* architected for high throughput. Even if events are later deemed unnecessary or
* filtered out, we encourage you to log them to Orb if they may be relevant to
* billing calculations in the future.
*
* To take advantage of the real-time features of the Orb platform and avoid any
* chance of dropped events by producers, we recommend reporting events to Orb
* frequently. Optionally, events can also be briefly aggregated at the source, as
* this API accepts an array of event bodies.
*
* Orb does not currently enforce a hard rate-limit for API usage or a maximum
* request payload size, but please give us a heads up if you’re changing either of
* these factors by an order of magnitude from initial setup.
*
* ## Testing in debug mode
*
* The ingestion API supports a debug mode, which returns additional verbose output
* to indicate which event idempotency keys were newly ingested or duplicates from
* previous requests. To enable this mode, mark `debug=true` as a query parameter.
*
* If `debug=true` is not specified, the response will only contain
* `validation_failed`. Orb will still honor the idempotency guarantees set
* [here](/events-and-metrics/event-ingestion#event-volume-and-concurrency) in all
* cases.
*
* We strongly recommend that you only use debug mode as part of testing your
* initial Orb integration. Once you're ready to switch to production, disable
* debug mode to take advantage of improved performance and maximal throughput.
*
* #### Example: ingestion response with `debug=true`
*
* ```json
* {
* "debug": {
* "duplicate": [],
* "ingested": ["B7E83HDMfJPAunXW", "SJs5DQJ3TnwSqEZE", "8SivfDsNKwCeAXim"]
* },
* "validation_failed": []
* }
* ```
*
* #### Example: ingestion response with `debug=false`
*
* ```json
* {
* "validation_failed": []
* }
* ```
*/
ingest(params, options) {
const { backfill_id, debug, ...body } = params;
return this._client.post('/ingest', { query: { backfill_id, debug }, body, ...options });
}
/**
* This endpoint returns a filtered set of events for an account in a
* [paginated list format](/api-reference/pagination).
*
* Note that this is a `POST` endpoint rather than a `GET` endpoint because it
* employs a JSON body for search criteria rather than query parameters, allowing
* for a more flexible search syntax.
*
* Note that a search criteria _must_ be specified. Currently, Orb supports the
* following criteria:
*
* - `event_ids`: This is an explicit array of IDs to filter by. Note that an
* event's ID is the `idempotency_key` that was originally used for ingestion.
*
* By default, Orb will not throw a `404` if no events matched, Orb will return an
* empty array for `data` instead.
*/
search(body, options) {
return this._client.post('/events/search', { body, ...options });
}
}
exports.Events = Events;
Events.Backfills = backfills_1.Backfills;
Events.BackfillListResponsesPage = backfills_1.BackfillListResponsesPage;
Events.Volume = volume_1.Volume;
//# sourceMappingURL=events.js.map