Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## Unreleased
- Add Account Accesses API
- Add Billing API

## [2.7.0] - 2026-02-24
- Add Sandbox Messages API
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,11 @@ Contact management:

General:

- Templates CRUD – [`email_templates_api.rb`](examples/email_templates_api.rb)
- Action Mailer – [`action_mailer.rb`](examples/action_mailer.rb)
- Accounts API – [`accounts_api.rb`](examples/accounts_api.rb)
- Account Accesses – [`account_accesses_api.rb`](examples/account_accesses_api.rb)
- Account Accesses API – [`account_accesses_api.rb`](examples/account_accesses_api.rb)
- Billing API – [`billing_api.rb`](examples/billing_api.rb)
- Templates API – [`email_templates_api.rb`](examples/email_templates_api.rb)
- Action Mailer – [`action_mailer.rb`](examples/action_mailer.rb)

## Migration guide v1 → v2

Expand Down
23 changes: 23 additions & 0 deletions examples/billing_api.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require 'mailtrap'

account_id = 3229
client = Mailtrap::Client.new(api_key: 'your-api-key')
billing = Mailtrap::BillingAPI.new(account_id, client)

# Get current billing cycle usage
billing.usage
# => #<struct Mailtrap::BillingUsage
# billing={cycle_start: "2026-02-06T12:59:54.000Z", cycle_end: "2026-03-06T12:59:54.000Z"},
# testing={
# plan: {name: "Team"},
# usage: {
# sent_messages_count: {current: 0, limit: 5000},
# forwarded_messages_count: {current: 0, limit: 500}
# }
# },
# sending={
# plan: {name: "Basic 10K"},
# usage: {
# sent_messages_count: {current: 0, limit: 10000}
# }
# }>
1 change: 1 addition & 0 deletions lib/mailtrap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require_relative 'mailtrap/version'
require_relative 'mailtrap/accounts_api'
require_relative 'mailtrap/account_accesses_api'
require_relative 'mailtrap/billing_api'
require_relative 'mailtrap/email_templates_api'
require_relative 'mailtrap/contacts_api'
require_relative 'mailtrap/contact_lists_api'
Expand Down
18 changes: 18 additions & 0 deletions lib/mailtrap/billing_api.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

require_relative 'base_api'
require_relative 'billing_usage'

module Mailtrap
class BillingAPI
include BaseAPI

# Get current billing cycle usage
# @return [BillingUsage] Billing usage data for account
# @!macro api_errors
def usage
response = client.get("/api/accounts/#{account_id}/billing/usage")
build_entity(response, BillingUsage)
end
end
end
16 changes: 16 additions & 0 deletions lib/mailtrap/billing_usage.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

module Mailtrap
# Data Transfer Object for Billing Usage data
# @see https://docs.mailtrap.io/developers/account-management/billing
# @attr_reader billing [Hash] The billing cycle details
# @attr_reader testing [Hash] Testing subscription usage
# @attr_reader sending [Hash] Sending subscription usage
#
BillingUsage = Struct.new(
:billing,
:testing,
:sending,
keyword_init: true
)
end
2 changes: 1 addition & 1 deletion lib/mailtrap/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module Mailtrap
# Data Transfer Object for Project
# @see https://api-docs.mailtrap.io/docs/mailtrap-api-docs/ee252e413d78a-create-project
# @see https://docs.mailtrap.io/developers/email-sandbox/projects
# @attr_reader id [Integer] The project ID
# @attr_reader name [String] The project name
# @attr_reader share_links [Hash] Admin and viewer share links
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions spec/mailtrap/billing_api_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

RSpec.describe Mailtrap::BillingAPI, :vcr do
subject(:billing) { described_class.new(account_id, client) }

let(:account_id) { ENV.fetch('MAILTRAP_ACCOUNT_ID', 1_111_111) }
let(:client) { Mailtrap::Client.new(api_key: ENV.fetch('MAILTRAP_API_KEY', 'local-api-key')) }

describe '#usage' do
subject(:usage) { billing.usage }

it 'maps response data to Billing object' do
expect(usage).to be_a(Mailtrap::BillingUsage)

expect(usage).to match_struct(
billing: { cycle_start: '2026-02-06T12:59:54.000Z', cycle_end: '2026-03-06T12:59:54.000Z' },
testing: { plan: { name: 'Team' },
usage: { sent_messages_count: { current: 0, limit: 5000 },
forwarded_messages_count: { current: 0, limit: 500 } } },
sending: { plan: { name: 'Basic 10K' }, usage: { sent_messages_count: { current: 0, limit: 10_000 } } }
)
end

context 'when api key is incorrect' do
let(:client) { Mailtrap::Client.new(api_key: 'incorrect-api-key') }

it 'raises authorization error' do
expect { usage }.to raise_error do |error|
expect(error).to be_a(Mailtrap::AuthorizationError)
expect(error.message).to include('Incorrect API token')
expect(error.messages.any? { |msg| msg.include?('Incorrect API token') }).to be true
end
end
end
end
end
77 changes: 77 additions & 0 deletions spec/mailtrap/billing_usage_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# frozen_string_literal: true

RSpec.describe Mailtrap::BillingUsage do
describe '#initialize' do
subject(:billing) { described_class.new(attributes) }

let(:attributes) do
{
billing: {
cycle_start: '2024-02-15T21:11:59.624Z',
cycle_end: '2024-02-15T21:11:59.624Z'
},
testing: {
plan: {
name: 'Individual'
},
usage: {
sent_messages_count: {
current: 1234,
limit: 5000
},
forwarded_messages_count: {
current: 0,
limit: 100
}
}
},
sending: {
plan: {
name: 'Basic 10K'
},
usage: {
sent_messages_count: {
current: 6789,
limit: 10_000
}
}
}
}
end

it 'creates a billing data with all attributes' do
expect(billing).to match_struct(
billing: {
cycle_start: '2024-02-15T21:11:59.624Z',
cycle_end: '2024-02-15T21:11:59.624Z'
},
testing: {
plan: {
name: 'Individual'
},
usage: {
sent_messages_count: {
current: 1234,
limit: 5000
},
forwarded_messages_count: {
current: 0,
limit: 100
}
}
},
sending: {
plan: {
name: 'Basic 10K'
},
usage: {
sent_messages_count: {
current: 6789,
limit: 10_000
}
}
}
)
end
end
end