No description
  • Elixir 87.2%
  • Nix 9.3%
  • Erlang 3.5%
Find a file
2026-02-14 10:28:22 -06:00
.nix-hex test: achieve 100% test coverage across all modules 2026-02-13 17:47:05 -06:00
.nix-mix feat: expand API coverage — invoices, payments, products, users, work orders, technicians, properties, addresses, coverage areas, inventory locations/models 2026-02-13 17:33:38 -06:00
.nix-postgres initial 2026-02-14 10:03:02 -06:00
lib test: achieve 100% test coverage across all modules 2026-02-13 17:47:05 -06:00
nix initial 2026-02-14 10:03:02 -06:00
test test: achieve 100% test coverage across all modules 2026-02-13 17:47:05 -06:00
.credo.exs Initial commit: Gaiia Elixir API client library v0.1.0 2026-02-13 17:02:28 -06:00
.envrc feat: add Nix flake for Elixir 1.19/OTP 28 dev shell 2026-02-13 19:14:42 -06:00
.formatter.exs Initial commit: Gaiia Elixir API client library v0.1.0 2026-02-13 17:02:28 -06:00
.gitignore feat: add Nix flake for Elixir 1.19/OTP 28 dev shell 2026-02-13 19:14:42 -06:00
.pre-commit-config.yaml precommit update 2026-02-14 10:28:22 -06:00
flake.lock initial 2026-02-14 10:03:02 -06:00
flake.nix initial 2026-02-14 10:03:02 -06:00
LICENSE Initial commit: Gaiia Elixir API client library v0.1.0 2026-02-13 17:02:28 -06:00
mix.exs test: achieve 100% test coverage across all modules 2026-02-13 17:47:05 -06:00
mix.lock test: achieve 100% test coverage across all modules 2026-02-13 17:47:05 -06:00
README.md Initial commit: Gaiia Elixir API client library v0.1.0 2026-02-13 17:02:28 -06:00
schema_introspection.json feat: expand API coverage — invoices, payments, products, users, work orders, technicians, properties, addresses, coverage areas, inventory locations/models 2026-02-13 17:33:38 -06:00

Gaiia

Elixir client library for the Gaiia ISP/WISP billing platform GraphQL API.

Installation

Add gaiia to your list of dependencies in mix.exs:

def deps do
  [
    {:gaiia, "~> 0.1.0"}
  ]
end

Configuration

# config/config.exs
config :gaiia,
  api_key: "your-api-key",
  endpoint: "https://api.gaiia.com/api/v1"  # optional, this is the default

All functions also accept api_key: and endpoint: as per-call options, which override application config.

Usage

Accounts

# Fetch all accounts eagerly
{:ok, accounts} = Gaiia.accounts()

# Stream lazily (fetches pages on demand)
Gaiia.stream_accounts() |> Enum.take(10)

# With per-call API key
{:ok, accounts} = Gaiia.accounts(api_key: "other-key")

Network Sites

{:ok, sites} = Gaiia.network_sites()
Gaiia.stream_network_sites() |> Enum.to_list()

Inventory Items

{:ok, items} = Gaiia.inventory_items()

# Update an item
{:ok, result} = Gaiia.update_inventory_item("item-id", %{"ipAddressV4" => "10.0.0.1"})

Billing Subscriptions

{:ok, subs} = Gaiia.billing_subscriptions()

Tickets

{:ok, ticket} = Gaiia.create_ticket(%{
  subject: "Internet down",
  description: "Customer reports no connectivity",
  entity_id: "account-123",
  entity_type: "Account"
})

Notes

{:ok, note} = Gaiia.create_note("Account", "account-123", "Customer called about billing.")

Pagination

All list operations support two modes:

  • Stream (lazy) — Pages are fetched on demand. Use Enum.take/2 to limit.
  • List (eager) — All pages are fetched and returned as a flat list.
# Lazy — only fetches pages as needed
Gaiia.stream_accounts() |> Enum.take(5)

# Eager — fetches everything
{:ok, all_accounts} = Gaiia.accounts()

# Custom page size
Gaiia.stream_accounts(page_size: 50) |> Enum.to_list()

Webhook Verification

Gaiia sends webhooks signed with HMAC-SHA256. Verify them before processing:

case Gaiia.Webhooks.verify(raw_body, signature_header, "your-shared-secret") do
  {:ok, payload} ->
    event = Gaiia.Webhooks.parse_event(payload)
    # event.event_type, event.entity_type, event.entity_id, event.data
    handle_event(event)

  {:error, :invalid_signature} ->
    send_resp(conn, 401, "Invalid signature")
end

Error Handling

All operations return {:ok, result} or {:error, %Gaiia.Error{}}:

case Gaiia.accounts() do
  {:ok, accounts} -> process(accounts)
  {:error, %Gaiia.Error{code: :unauthorized}} -> refresh_credentials()
  {:error, %Gaiia.Error{code: :rate_limited, details: %{retry_after: seconds}}} -> retry_later(seconds)
  {:error, %Gaiia.Error{code: code, message: msg}} -> log_error(code, msg)
end

Testing

The library uses Req for HTTP. In tests, configure a plug to mock responses:

# In test setup
Application.put_env(:gaiia, :req_plug, fn conn ->
  conn
  |> Plug.Conn.put_resp_content_type("application/json")
  |> Plug.Conn.send_resp(200, Jason.encode!(%{
    "data" => %{"accounts" => %{"edges" => [], "pageInfo" => %{"hasNextPage" => false}}}
  }))
end)

Run tests:

mix test

License

MIT — see LICENSE.