PinStripe.Client (PinStripe v0.3.4)
View SourceA minimal Stripe API client built on Req.
This module provides a simple interface for interacting with the Stripe API, covering the most common operations while maintaining an escape hatch to Req for advanced use cases.
Configuration
Configure your Stripe API key in your application config:
config :pin_stripe,
stripe_api_key: "sk_test_..."For testing, configure the client to use Req.Test:
config :pin_stripe,
req_options: [plug: {Req.Test, PinStripe}]CRUD Operations
The client supports standard CRUD operations with a consistent API:
Read Operations
Fetch individual resources by ID (string):
Client.read("cus_123")
# => {:ok, %Req.Response{body: %{"id" => "cus_123", ...}}}List resources by entity type (atom):
Client.read(:customers, limit: 10)
# => {:ok, %Req.Response{body: %{"object" => "list", "data" => [...]}}}Create Operations
Create resources using entity type atoms:
Client.create(:customers, %{email: "user@example.com"})
# => {:ok, %Req.Response{body: %{"id" => "cus_new", ...}}}Update Operations
Update resources by ID:
Client.update("cus_123", %{name: "New Name"})
# => {:ok, %Req.Response{body: %{"id" => "cus_123", "name" => "New Name"}}}Delete Operations
Delete resources by ID:
Client.delete("cus_123")
# => {:ok, %Req.Response{body: %{"id" => "cus_123", "deleted" => true}}}Supported Entity Types
The following entity types are supported (as atoms):
:customers- Customer objects:products- Product objects:prices- Price objects:subscriptions- Subscription objects:invoices- Invoice objects:events- Event objects:checkout_sessions- Checkout Session objects
Error Handling
All operations return {:ok, response} or {:error, reason} tuples:
Client.read(:invalid_entity)
# => {:error, :unrecognized_entity_type}
# HTTP errors return the response with error details
Client.read("cus_nonexistent")
# => {:error, %Req.Response{status: 404, body: %{"error" => ...}}}Bang Functions
Each CRUD function has a bang version (read!/2, create!/3, update!/3, delete!/2)
that raises a RuntimeError instead of returning error tuples:
# Raises on error
response = Client.read!("cus_123")
customer = response.body
# Raises RuntimeError: "Unrecognized entity type: :invalid"
Client.read!(:invalid)
# Raises RuntimeError: "Request failed with status 404: ..."
Client.read!("cus_nonexistent")ID Prefix Recognition
The client automatically recognizes Stripe ID prefixes:
cus_*→/customers/{id}product_*→/products/{id}price_*→/prices/{id}sub_*→/subscriptions/{id}inv_*→/invoices/{id}evt_*→/events/{id}cs_*→/checkout/sessions/{id}
Examples
# Fetch a customer
{:ok, response} = Client.read("cus_123")
customer = response.body
# List customers with pagination
{:ok, response} = Client.read(:customers, limit: 10, starting_after: "cus_123")
customers = response.body["data"]
# Create a customer
{:ok, response} = Client.create(:customers, %{
email: "customer@example.com",
name: "Jane Doe"
})
# Update a customer
{:ok, response} = Client.update("cus_123", %{
metadata: %{user_id: "12345"}
})
# Delete a customer
{:ok, response} = Client.delete("cus_123")
Summary
Functions
Creates a new resource.
Creates a new resource, raising on error.
Deletes a resource by ID.
Deletes a resource by ID, raising on error.
Converts an entity atom to its API path.
Parses a Stripe ID or URL path into a full API path.
Reads a resource by ID or lists resources by entity type.
Reads a resource by ID or lists resources by entity type, raising on error.
Updates an existing resource by ID.
Updates an existing resource by ID, raising on error.
Functions
Creates a new resource.
Parameters
entity- Atom representing the entity type (e.g.,:customers,:products)params- Map of parameters for the resourceoptions- Keyword list of additional Req options
Examples
iex> Req.Test.stub(PinStripe, fn conn ->
...> Req.Test.json(conn, %{id: "cus_new", email: "new@example.com"})
...> end)
iex> {:ok, response} = PinStripe.Client.create(:customers, %{email: "new@example.com"})
iex> response.body["id"]
"cus_new"
# Unrecognized entity type
iex> PinStripe.Client.create(:invalid, %{})
{:error, :unrecognized_entity_type}
Creates a new resource, raising on error.
Similar to create/3 but raises a RuntimeError on error instead of returning an error tuple.
Parameters
entity- Atom representing the entity typeparams- Map of parameters for the resourceoptions- Keyword list of additional Req options
Examples
iex> Req.Test.stub(PinStripe, fn conn ->
...> Req.Test.json(conn, %{id: "cus_new"})
...> end)
iex> response = PinStripe.Client.create!(:customers, %{email: "test@example.com"})
iex> response.body["id"]
"cus_new"
Deletes a resource by ID.
Parameters
id- String ID of the resource (e.g.,"cus_123")options- Keyword list of additional Req options
Examples
iex> Req.Test.stub(PinStripe, fn conn ->
...> Req.Test.json(conn, %{id: "cus_123", deleted: true})
...> end)
iex> {:ok, response} = PinStripe.Client.delete("cus_123")
iex> response.body["deleted"]
true
Deletes a resource by ID, raising on error.
Similar to delete/2 but raises a RuntimeError on error instead of returning an error tuple.
Parameters
id- String ID of the resourceoptions- Keyword list of additional Req options
Examples
iex> Req.Test.stub(PinStripe, fn conn ->
...> Req.Test.json(conn, %{id: "cus_123", deleted: true})
...> end)
iex> response = PinStripe.Client.delete!("cus_123")
iex> response.body["deleted"]
true
Converts an entity atom to its API path.
Returns {:ok, path} for recognized entities, or {:error, :unrecognized_entity_type} otherwise.
Examples
iex> PinStripe.Client.entity_to_path(:customers)
{:ok, "/customers"}
iex> PinStripe.Client.entity_to_path(:products)
{:ok, "/products"}
iex> PinStripe.Client.entity_to_path(:invalid)
{:error, :unrecognized_entity_type}
Parses a Stripe ID or URL path into a full API path.
Recognizes Stripe ID prefixes and converts them to the appropriate API endpoint. Custom paths are returned as-is.
Examples
iex> PinStripe.Client.parse_url("cus_123")
"/customers/cus_123"
iex> PinStripe.Client.parse_url("product_abc")
"/products/product_abc"
iex> PinStripe.Client.parse_url("/custom/path")
"/custom/path"
Reads a resource by ID or lists resources by entity type.
Parameters
id_or_entity- Either a string ID (e.g.,"cus_123") or an atom entity type (e.g.,:customers)options- Keyword list of options (e.g., query parameters for list operations)
Examples
# Fetch by ID
iex> Req.Test.stub(PinStripe, fn conn ->
...> Req.Test.json(conn, %{id: "cus_123", email: "test@example.com"})
...> end)
iex> {:ok, response} = PinStripe.Client.read("cus_123")
iex> response.body["id"]
"cus_123"
# List resources
iex> Req.Test.stub(PinStripe, fn conn ->
...> Req.Test.json(conn, %{object: "list", data: []})
...> end)
iex> {:ok, response} = PinStripe.Client.read(:customers)
iex> response.body["object"]
"list"
# Unrecognized entity type
iex> PinStripe.Client.read(:invalid)
{:error, :unrecognized_entity_type}
Reads a resource by ID or lists resources by entity type, raising on error.
Similar to read/2 but raises a RuntimeError on error instead of returning an error tuple.
Parameters
id_or_entity- Either a string ID or an atom entity typeoptions- Keyword list of options
Examples
iex> Req.Test.stub(PinStripe, fn conn ->
...> Req.Test.json(conn, %{id: "cus_123"})
...> end)
iex> response = PinStripe.Client.read!("cus_123")
iex> response.body["id"]
"cus_123"
Updates an existing resource by ID.
Parameters
id- String ID of the resource (e.g.,"cus_123")params- Map of parameters to updateoptions- Keyword list of additional Req options
Examples
iex> Req.Test.stub(PinStripe, fn conn ->
...> Req.Test.json(conn, %{id: "cus_123", name: "Updated"})
...> end)
iex> {:ok, response} = PinStripe.Client.update("cus_123", %{name: "Updated"})
iex> response.body["name"]
"Updated"
Updates an existing resource by ID, raising on error.
Similar to update/3 but raises a RuntimeError on error instead of returning an error tuple.
Parameters
id- String ID of the resourceparams- Map of parameters to updateoptions- Keyword list of additional Req options
Examples
iex> Req.Test.stub(PinStripe, fn conn ->
...> Req.Test.json(conn, %{id: "cus_123", name: "Updated"})
...> end)
iex> response = PinStripe.Client.update!("cus_123", %{name: "Updated"})
iex> response.body["name"]
"Updated"