Class: Nahook::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/nahook/client.rb

Overview

Client for sending webhook payloads through the Nahook ingestion API.

Supports sending to specific endpoints, fan-out by event type, and batch operations. Includes configurable retry with exponential backoff.

Examples:

Basic usage

client = Nahook::Client.new("nhk_us_your_api_key")
client.send("ep_abc123", payload: { order_id: "12345" })

With options

client = Nahook::Client.new("nhk_us_your_api_key",
  base_url: "https://custom.nahook.com",
  timeout_ms: 15_000,
  retries: 3
)

Instance Method Summary collapse

Constructor Details

#initialize(api_key, base_url: nil, timeout_ms: HttpClient::DEFAULT_TIMEOUT_MS, retries: 0, adapter: nil, connection: nil) ⇒ Client

Returns a new instance of Client.

Parameters:

  • api_key (String)

    API key (must start with “nhk_”)

  • base_url (String) (defaults to: nil)

    API base URL

  • timeout_ms (Integer) (defaults to: HttpClient::DEFAULT_TIMEOUT_MS)

    request timeout in milliseconds (default: 30000)

  • retries (Integer) (defaults to: 0)

    number of retry attempts for retryable errors

  • adapter (Symbol, nil) (defaults to: nil)

    Faraday adapter to use (defaults to ‘:net_http_persistent` for keep-alive). Useful for swapping to e.g. `:typhoeus` for high-throughput workloads without building a full Faraday connection.

  • connection (Faraday::Connection, nil) (defaults to: nil)

    a fully-configured Faraday connection. When supplied, ‘base_url`, `timeout_ms`, and `adapter` are ignored — the caller owns connection configuration (custom middleware, instrumentation, proxies, mTLS, etc.).

Raises:

  • (ArgumentError)

    if the API key does not start with “nhk_”



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/nahook/client.rb', line 35

def initialize(api_key, base_url: nil, timeout_ms: HttpClient::DEFAULT_TIMEOUT_MS,
               retries: 0, adapter: nil, connection: nil)
  unless api_key.start_with?("nhk_")
    raise ArgumentError, "Invalid API key: must start with 'nhk_'"
  end

  resolved_url = base_url || HttpClient.resolve_base_url(api_key)

  http_kwargs = {
    token: api_key,
    base_url: resolved_url,
    timeout_ms: timeout_ms,
    retries: retries,
  }
  http_kwargs[:adapter]    = adapter    if adapter
  http_kwargs[:connection] = connection if connection

  @http = HttpClient.new(**http_kwargs)
end

Instance Method Details

#send(endpoint_id, payload:, idempotency_key: nil) ⇒ Hash

Send a payload to a specific endpoint.

Parameters:

  • endpoint_id (String)

    the endpoint public ID (e.g. “ep_abc123”)

  • payload (Hash)

    the webhook payload

  • idempotency_key (String, nil) (defaults to: nil)

    optional idempotency key (auto-generated if omitted)

Returns:

  • (Hash)

    response with “deliveryId”, “idempotencyKey”, and “status” keys

Raises:



64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/nahook/client.rb', line 64

def send(endpoint_id, payload:, idempotency_key: nil)
  key = idempotency_key || SecureRandom.uuid

  @http.request(
    method: :post,
    path: "/api/ingest/#{CGI.escape(endpoint_id)}",
    body: {
      "payload" => payload,
      "idempotencyKey" => key
    }
  )
end

#send_batch(items) ⇒ Hash

Batch send to multiple specific endpoints (max 20 items).

Examples:

client.send_batch([
  { endpoint_id: "ep_abc", payload: { order: 1 } },
  { endpoint_id: "ep_def", payload: { order: 2 }, idempotency_key: "key-2" }
])

Parameters:

  • items (Array<Hash>)

    list of items, each with :endpoint_id, :payload, and optional :idempotency_key

Returns:

  • (Hash)

    response with “items” key containing per-item results

Raises:



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/nahook/client.rb', line 106

def send_batch(items)
  mapped = items.map do |item|
    entry = {
      "endpointId" => item[:endpoint_id] || item["endpoint_id"],
      "payload" => item[:payload] || item["payload"]
    }
    key = item[:idempotency_key] || item["idempotency_key"]
    entry["idempotencyKey"] = key if key
    entry
  end

  @http.request(
    method: :post,
    path: "/api/ingest/batch",
    body: { "items" => mapped }
  )
end

#trigger(event_type, payload:, metadata: nil) ⇒ Hash

Fan-out a payload by event type to all subscribed endpoints.

Parameters:

  • event_type (String)

    the event type name (e.g. “order.paid”)

  • payload (Hash)

    the webhook payload

  • metadata (Hash, nil) (defaults to: nil)

    optional metadata key-value pairs

Returns:

  • (Hash)

    response with “eventTypeId”, “deliveryIds”, and “status” keys

Raises:



84
85
86
87
88
89
90
91
92
93
# File 'lib/nahook/client.rb', line 84

def trigger(event_type, payload:, metadata: nil)
  body = { "payload" => payload }
  body["metadata"] =  if 

  @http.request(
    method: :post,
    path: "/api/ingest/event/#{CGI.escape(event_type)}",
    body: body
  )
end

#trigger_batch(items) ⇒ Hash

Batch fan-out by event types (max 20 items).

Examples:

client.trigger_batch([
  { event_type: "order.paid", payload: { order_id: "123" } },
  { event_type: "user.created", payload: { user_id: "456" } }
])

Parameters:

  • items (Array<Hash>)

    list of items, each with :event_type, :payload, and optional :metadata

Returns:

  • (Hash)

    response with “items” key containing per-item results

Raises:



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/nahook/client.rb', line 135

def trigger_batch(items)
  mapped = items.map do |item|
    entry = {
      "eventType" => item[:event_type] || item["event_type"],
      "payload" => item[:payload] || item["payload"]
    }
    meta = item[:metadata] || item["metadata"]
    entry["metadata"] = meta if meta
    entry
  end

  @http.request(
    method: :post,
    path: "/api/ingest/event/batch",
    body: { "items" => mapped }
  )
end