# AbacatePay Elixir SDK
[](https://hex.pm/packages/abacatepay_elixir_sdk)
[](https://hexdocs.pm/abacatepay_elixir_sdk)
[](https://github.com/iagocavalcante/abacatepay-elixir-sdk/blob/main/LICENSE)
The official Elixir SDK for [AbacatePay](https://abacatepay.com/) - Brazil's modern payment platform. Build secure, fast payment integrations with PIX, cards, and billing management.
## Features
- 🏦 **Complete API Coverage** - All AbacatePay endpoints supported
- 🔒 **Production Ready** - Robust error handling and security
- 📊 **Comprehensive Testing** - 100% API coverage with VCR cassettes
- 🚀 **Modern Elixir** - Built with Req, Jason, and OTP best practices
- 📖 **Full Documentation** - Complete guides and API reference
- 🐛 **Developer Friendly** - Detailed error messages and debugging support
## Installation
Add `abacatepay_elixir_sdk` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:abacatepay_elixir_sdk, "~> 0.1.0"}
]
end
```
Then run:
```bash
mix deps.get
```
## Configuration
### Environment Variables (Recommended)
```bash
export ABACATEPAY_API_TOKEN="abc_dev_your_token_here"
export ABACATEPAY_ENVIRONMENT="sandbox" # or "production"
```
### Application Configuration
In your `config/config.exs`:
```elixir
config :abacatepay_elixir_sdk,
api_token: System.get_env("ABACATEPAY_API_TOKEN"),
environment: :sandbox # :sandbox or :production
```
For production, use `config/runtime.exs`:
```elixir
import Config
if config_env() == :prod do
config :abacatepay_elixir_sdk,
api_token: System.get_env("ABACATEPAY_API_TOKEN") || raise("ABACATEPAY_API_TOKEN not set"),
environment: :production
end
```
## Quick Start
```elixir
# Create a simple PIX payment
alias AbacatepayElixirSdk.PixClient
params = %{
amount: 1999, # R$ 19.99 in cents
description: "Premium Subscription"
}
case PixClient.create_qrcode(params) do
{:ok, qr_data} ->
# qr_data contains: id, qrCode, paymentLink
IO.puts("PIX Code: #{qr_data["qrCode"]}")
IO.puts("Payment Link: #{qr_data["paymentLink"]}")
{:error, reason} ->
IO.puts("Error: #{reason}")
end
```
## API Reference
### Store Operations
```elixir
alias AbacatepayElixirSdk.StoreClient
# Get store details and balance
{:ok, store} = StoreClient.get()
# Returns: %{"id" => "...", "name" => "...", "balance" => %{...}}
```
### Billing Operations
```elixir
alias AbacatepayElixirSdk.BillingClient
# Create a billing/invoice
params = %{
amount: 2999, # R$ 29.99 in cents
description: "Monthly Subscription",
frequency: "oneTime" # or "monthly", "yearly"
}
{:ok, billing} = BillingClient.create(params)
# List all billings
{:ok, billings} = BillingClient.list()
```
### Customer Management
```elixir
alias AbacatepayElixirSdk.CustomerClient
# Create a customer
customer_params = %{
name: "João Silva",
email: "joao@example.com",
cellphone: "11999999999",
taxId: "11144477735" # Valid CPF
}
{:ok, customer} = CustomerClient.create(customer_params)
# List all customers
{:ok, customers} = CustomerClient.list()
```
### PIX Operations
```elixir
alias AbacatepayElixirSdk.PixClient
# Create PIX QR Code
pix_params = %{
amount: 5000, # R$ 50.00
description: "Product Purchase"
}
{:ok, qr_data} = PixClient.create_qrcode(pix_params)
# Check payment status
{:ok, status} = PixClient.check_status(qr_data["id"])
# Simulate payment (development mode only)
{:ok, payment} = PixClient.simulate_payment(qr_data["id"], %{test: "data"})
```
### Coupon Management
```elixir
alias AbacatepayElixirSdk.CouponClient
# Create a discount coupon
coupon_params = %{
code: "SAVE20",
type: "percentage",
value: 20,
maxUses: 100,
expiresAt: "2024-12-31T23:59:59Z",
notes: "20% off for new customers"
}
{:ok, coupon} = CouponClient.create(coupon_params)
# List all coupons
{:ok, coupons} = CouponClient.list()
```
### Withdrawal Operations
> **Note**: Withdrawal operations are only available in production mode.
```elixir
alias AbacatepayElixirSdk.WithdrawClient
# Create withdrawal
withdraw_params = %{
amount: 10000, # R$ 100.00
externalId: "withdraw-001",
bankAccount: %{
bank: "001",
agency: "1234",
account: "12345678",
accountType: "checking"
}
}
{:ok, withdraw} = WithdrawClient.create(withdraw_params)
# Get withdrawal by external ID
{:ok, withdraw} = WithdrawClient.get("withdraw-001")
# List all withdrawals
{:ok, withdrawals} = WithdrawClient.list()
```
## Error Handling
The SDK provides structured error handling:
```elixir
case BillingClient.create(invalid_params) do
{:ok, billing} ->
# Success case
process_billing(billing)
{:error, "body must have required property 'frequency'"} ->
# Validation error from API
{:error, :invalid_frequency}
{:error, %{reason: :timeout}} ->
# Network timeout
{:error, :network_timeout}
{:error, reason} ->
# Other errors
{:error, reason}
end
```
## Testing
The SDK includes comprehensive tests with VCR cassettes for reliable testing:
```bash
# Run all tests
mix test
# Run tests with coverage
mix test --cover
# Run specific test file
mix test test/abacatepay_elixir_sdk/billing_client_test.exs
```
### Testing Your Integration
```elixir
# In your test files
use ExUnit.Case
use ExVCR.Mock, adapter: ExVCR.Adapter.Finch
test "creates billing successfully" do
use_cassette "billing_create_success" do
params = %{amount: 1000, description: "Test", frequency: "oneTime"}
assert {:ok, billing} = BillingClient.create(params)
end
end
```
## Environment Support
### Sandbox (Development)
- All endpoints available except withdrawals
- Use test API tokens starting with `abc_dev_`
- Payment simulation available
- Safe for development and testing
### Production
- All endpoints available including withdrawals
- Use production API tokens starting with `abc_live_`
- Real payment processing
- Requires PCI compliance for card operations
## Rate Limiting & Best Practices
- **Rate Limits**: 100 requests per minute per API key
- **Retries**: Implement exponential backoff for failed requests
- **Idempotency**: Use unique external IDs for create operations
- **Monitoring**: Log all API responses for debugging
```elixir
# Example with retry logic
defmodule PaymentService do
def create_billing_with_retry(params, retries \\ 3) do
case BillingClient.create(params) do
{:ok, billing} -> {:ok, billing}
{:error, reason} when retries > 0 ->
Process.sleep(1000)
create_billing_with_retry(params, retries - 1)
error -> error
end
end
end
```
## Security
- ✅ **API Keys**: Never commit API keys to version control
- ✅ **Environment Variables**: Use secure environment management
- ✅ **HTTPS Only**: All API calls use HTTPS encryption
- ✅ **Request Signing**: Built-in request authentication
- ✅ **Data Filtering**: Sensitive data excluded from logs
## Support & Resources
- 📖 **[API Documentation](https://docs.abacatepay.com/)** - Complete API reference
- 💬 **[Discord Community](https://discord.gg/abacatepay)** - Developer support
- 🐛 **[Issue Tracker](https://github.com/iagocavalcante/abacatepay-elixir-sdk/issues)** - Bug reports
- 📧 **[Email Support](mailto:dev@abacatepay.com)** - Technical questions
## Contributing
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## Changelog
See [CHANGELOG.md](CHANGELOG.md) for release notes and migration guides.
## License
This SDK is licensed under the MIT License. See [LICENSE](LICENSE) for details.
---
<div align="center">
<strong>Built with ❤️ for the Elixir community</strong><br>
<a href="https://abacatepay.com">AbacatePay</a> •
<a href="https://docs.abacatepay.com">Documentation</a> •
<a href="https://github.com/iagocavalcante/abacatepay-elixir-sdk">GitHub</a>
</div>