> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.trygrant.com/api-reference/grant-events-api/events/ingest/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.trygrant.com/_mcp/server. # Synchronously ingest billable events POST https://api.trygrant.com/v1/events/ingest Content-Type: application/json Accepts a single billable event and inserts it synchronously into the database. Reference: https://docs.trygrant.com/api-reference/grant-events-api/events/ingest ## Authentication - `Authorization` header (bearer token, required) — API key obtained from the Grant dashboard ## Servers - `https://api.trygrant.com` (Production, default) - `http://localhost:8787` (Local development) ## Request ### Body (application/json) This endpoint expects an IngestSyncRequest. - `event_name` (string, required) — Name of the event - `idempotency_key` (string, required) — Unique key to prevent duplicate event processing - `customer_id` (string, required) — Customer identifier - `timestamp` (datetime, required) — Event timestamp in ISO 8601 UTC format (Z or +00:00) - `session_id` (string, optional) — Optional session identifier. When provided, it is persisted on the billable event and associated product usage events to group related events. - `properties` (map from string to any, optional) — Additional event properties ## Response ### 200 Events processed synchronously - `success` (boolean, required) - `status` (enum, required) — Processing outcome for the submitted event - Allowed values: `inserted`, `duplicate`, `failed` - `request_id` (string, required) — Request ID for tracing - `usage_id` (string, optional) — Created or existing billable event ID - `cost` (list of InngestSyncResponseCostItems, optional) — Aggregated event cost by wallet denomination. Present on successful requests. - `customer_balances` (list of InngestSyncResponseCustomerBalancesItems, optional) — Current customer wallet balances across denominations after ingestion. - `error` (InngestSyncResponseError, optional) ## Errors ### 400 Bad Request Error Invalid request - `success` (boolean, required) - `error` (ErrorResponseError, required) - `request_id` (string, optional) — Request ID for tracing ### 401 Unauthorized Error Unauthorized - `success` (boolean, required) - `error` (ErrorResponseError, required) - `request_id` (string, optional) — Request ID for tracing ### 413 Content Too Large Error Request body too large - `success` (boolean, required) - `error` (ErrorResponseError, required) - `request_id` (string, optional) — Request ID for tracing ### 429 Too Many Requests Error Rate limit exceeded - `success` (boolean, required) - `error` (ErrorResponseError, required) - `request_id` (string, optional) — Request ID for tracing ### 500 Internal Server Error Internal server error - `success` (boolean, required) - `error` (ErrorResponseError, required) - `request_id` (string, optional) — Request ID for tracing ## Types ### InngestSyncResponseCostItems - `amount` (string, required) — Total event cost charged for this denomination - `account_type` (enum, required) — Wallet denomination type - Allowed values: `pricing_unit`, `currency` - `pricing_unit_code` (string, optional) — Pricing unit code (present for pricing_unit entries) - `currency_code` (string, optional) — Currency code (present for currency entries) ### InngestSyncResponseCustomerBalancesItems - `balance` (string, required) — Current wallet balance after ingestion - `account_type` (enum, required) — Wallet denomination type - Allowed values: `pricing_unit`, `currency` - `pricing_unit_code` (string, optional) — Pricing unit code (present for pricing_unit entries) - `currency_code` (string, optional) — Currency code (present for currency entries) ### InngestSyncResponseError - `code` (string, required) - `message` (string, required) ### ErrorResponseError - `code` (string, required) - `message` (string, required) - `details` (any, optional) ## Examples **Request** ```json { "event_name": "api.request", "idempotency_key": "evt_abc123xyz", "customer_id": "cjld2cjxh0000qzrmn831i7rn", "timestamp": "2023-11-07T05:31:56Z" } ``` **Response** ```json { "success": true, "status": "inserted", "request_id": "req_abc123", "usage_id": "cm5x9z8nv0000h85r7l9p2k1m", "cost": [ { "amount": "120", "account_type": "pricing_unit", "pricing_unit_code": "api_call", "currency_code": "usd" } ], "customer_balances": [ { "balance": "980", "account_type": "pricing_unit", "pricing_unit_code": "api_call", "currency_code": "usd" } ], "error": { "code": "DATABASE_ERROR", "message": "Failed to insert event" } } ``` **SDK Code** ```python import requests url = "https://api.trygrant.com/v1/events/ingest" payload = { "event_name": "api.request", "idempotency_key": "evt_abc123xyz", "customer_id": "cjld2cjxh0000qzrmn831i7rn", "timestamp": "2023-11-07T05:31:56Z" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = 'https://api.trygrant.com/v1/events/ingest'; const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: '{"event_name":"api.request","idempotency_key":"evt_abc123xyz","customer_id":"cjld2cjxh0000qzrmn831i7rn","timestamp":"2023-11-07T05:31:56Z"}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```go package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api.trygrant.com/v1/events/ingest" payload := strings.NewReader("{\n \"event_name\": \"api.request\",\n \"idempotency_key\": \"evt_abc123xyz\",\n \"customer_id\": \"cjld2cjxh0000qzrmn831i7rn\",\n \"timestamp\": \"2023-11-07T05:31:56Z\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` ```ruby require 'uri' require 'net/http' url = URI("https://api.trygrant.com/v1/events/ingest") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"event_name\": \"api.request\",\n \"idempotency_key\": \"evt_abc123xyz\",\n \"customer_id\": \"cjld2cjxh0000qzrmn831i7rn\",\n \"timestamp\": \"2023-11-07T05:31:56Z\"\n}" response = http.request(request) puts response.read_body ``` ```java import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api.trygrant.com/v1/events/ingest") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"event_name\": \"api.request\",\n \"idempotency_key\": \"evt_abc123xyz\",\n \"customer_id\": \"cjld2cjxh0000qzrmn831i7rn\",\n \"timestamp\": \"2023-11-07T05:31:56Z\"\n}") .asString(); ``` ```php request('POST', 'https://api.trygrant.com/v1/events/ingest', [ 'body' => '{ "event_name": "api.request", "idempotency_key": "evt_abc123xyz", "customer_id": "cjld2cjxh0000qzrmn831i7rn", "timestamp": "2023-11-07T05:31:56Z" }', 'headers' => [ 'Authorization' => 'Bearer ', 'Content-Type' => 'application/json', ], ]); echo $response->getBody(); ``` ```csharp using RestSharp; var client = new RestClient("https://api.trygrant.com/v1/events/ingest"); var request = new RestRequest(Method.POST); request.AddHeader("Authorization", "Bearer "); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"event_name\": \"api.request\",\n \"idempotency_key\": \"evt_abc123xyz\",\n \"customer_id\": \"cjld2cjxh0000qzrmn831i7rn\",\n \"timestamp\": \"2023-11-07T05:31:56Z\"\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` ```swift import Foundation let headers = [ "Authorization": "Bearer ", "Content-Type": "application/json" ] let parameters = [ "event_name": "api.request", "idempotency_key": "evt_abc123xyz", "customer_id": "cjld2cjxh0000qzrmn831i7rn", "timestamp": "2023-11-07T05:31:56Z" ] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://api.trygrant.com/v1/events/ingest")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ``` > API documentation for Grant — billing infrastructure for usage-based pricing