Skip to content

feat: add customer portal endpoints, cursor pagination and webhook verification - #12

Merged
gastonrey merged 1 commit into
mainfrom
feat/customer-portal-endpoints
Oct 2, 2026
Merged

gastonrey merged 1 commit into
mainfrom
feat/customer-portal-endpoints

Conversation

@gastonrey

Copy link
Copy Markdown
Collaborator

Why

Factorial's Customer Portal is being opened to Hyperline-billed companies. It needs endpoints the gem does not wrap yet, and the v1 invoice list ignores customer_id, so filtering a customer's invoices returned other customers' documents.

What

  • Invoices#list_v2 / #get_v2 on GET /v2/invoices, with a CursorCollection for its cursor pagination (limit, cursor, next_cursor, has_more). customer_id and subscription_id filter correctly here. Credit notes are type: "refund".
  • Invoices#download moves to /v2/invoices/{id}/download and returns a Hyperline::Download (body, content_type, filename). It follows one redirect without forwarding the API key. Breaking for callers that compared the result to a String; to_str keeps string-like use working.
  • Invoices#charge accepts idempotency_key:.
  • Customers#get_v2, #payment_methods, #delete_payment_method, #portal.
  • Subscriptions#preview_timeline, #simulate_updates.
  • New Integrations#create_component_token(customer_id:) for the embedded React components.
  • Hyperline::Webhook.verify!(payload:, headers:, secret:): Svix-style HMAC-SHA256 check over id.timestamp.body, whsec_ secret, 5-minute tolerance, constant-time compare. Raises Hyperline::WebhookSignatureError.

Verification

  • bundle exec rspec: 144 examples, 0 failures. rubocop: no offenses.
  • Read-only calls against the Hyperline sandbox: the v2 list filters by customer and returns a cursor, downloads return a real PDF for invoices and credit notes, and the portal, payment-method and preview-timeline endpoints answer.
  • Version not bumped; changes are under ## [Unreleased] in the CHANGELOG.

@gastonrey
gastonrey marked this pull request as ready for review October 2, 2026 13:05
@gastonrey
gastonrey merged commit abd6a17 into main Oct 2, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants