Current section
Files
Jump to
Current section
Files
lib/plain.ex
defmodule Plain do
defp base_url, do: "https://core-api.uk.plain.com/graphql/v1"
defp token, do: Application.get_env(:plain, :token)
@createOrUpdateTenantMutation "mutations/upsertTenant.graphql" |> File.read!()
@spec createOrUpdateTenant(String.t(), String.t(), String.t() | nil) ::
{:ok, map()} | {:error, any()}
@doc """
# Upserting tenants
When upserting a tenant you need to specify an `externalId` which matches the id of the tenant in your own backend.
For example if your product is structured in teams, then when creating a tenant for a team you’d use the team’s id as the `externalId`.
To upsert a tenant you need the following permissions:
- `tenant:read`
- `tenant:create`
"""
def createOrUpdateTenant(identifier, name, url) do
send_request(@createOrUpdateTenantMutation, %{
"input" => %{
"identifier" => %{
"externalId" => identifier
},
"name" => name,
"externalId" => identifier,
"url" =>
if url != nil do
%{
"value" => url
}
else
nil
end
}
})
end
@spec createOrUpdateTenant(String.t(), String.t()) :: {:ok, map()} | {:error, any()}
def createOrUpdateTenant(identifier, name), do: createOrUpdateTenant(identifier, name, nil)
@addCustomerToTenantMutation "mutations/addCustomerToTenant.graphql" |> File.read!()
@spec addCustomerToTenant(String.t(), list(String.t())) :: {:ok, map()} | {:error, any()}
@doc """
# Add customers to tenants
You can add a customer to multiple tenants.
When selecting the customer you can chose how to identify them. This SDK uses the customer’s plain id.
For this mutation you need the following permissions:
- `customer:edit`
- `customerTenantMembership:create`
"""
def addCustomerToTenant(customerId, tenantIds) do
send_request(@addCustomerToTenantMutation, %{
"input" => %{
"customerIdentifier" => %{
"customerId" => customerId
},
"tenantIdentifiers" => Enum.map(tenantIds, &%{"externalId" => &1})
}
})
end
@removeCustomerFromTenantMutation "mutations/addCustomerToTenant.graphql" |> File.read!()
@spec removeCustomerFromTenant(String.t(), list(String.t())) :: {:ok, map()} | {:error, any()}
@doc """
# Remove customers from tenants
You can remove customers from multiple tenants in one API call.
When selecting the customer you can chose how to identify them. This SDK uses the customer’s plain id.
For this mutation you need the following permissions:
- `customer:edit`
- `customerTenantMembership:delete`
"""
def removeCustomerFromTenant(customerId, tenantIds) do
send_request(@removeCustomerFromTenantMutation, %{
"input" => %{
"customerIdentifier" => %{
"customerId" => customerId
},
"tenantIdentifiers" => Enum.map(tenantIds, &%{"externalId" => &1})
}
})
end
@createOrUpdateCustomerMutation "mutations/upsertCustomer.graphql" |> File.read!()
@spec createOrUpdateCustomer(String.t(), String.t(), String.t(), String.t() | nil) ::
{:ok, map()} | {:error, any()}
@doc """
# Upserting customers
Creating and updating customers is handled via a single API called `upsertCustomer`. You will find this name in both the API and this SDK.
When you upsert a customer, you define:
1. The identifier: This is the field you’d like to use to select the customer and is one of
- `emailAddress`: This is the customer’s email address. Within Plain email addresses are unique to customers.
- `customerId`: This is Plain’s customer ID. Implicitly if you use this as an identifier you will only be updating the customer since the customer can’t have an id unless it already exists.
- `externalId`: This is the customer’s id in your systems. If you previously set this it can be a powerful way of syncing customer details from your backend with Plain.
2. The customer details you’d like to use if creating the customer.
3. The customer details you’d like to update if the customer already exists.
When upserting a customer you will always get back a customer or an error.
## Upserting a customer
This operation requires the following permissions:
- `customer:create`
- `customer:edit`
"""
def createOrUpdateCustomer(email, externalIdentifier, fullName, name) do
send_request(@createOrUpdateCustomerMutation, %{
"input" => %{
"identifier" => %{
"externalId" => externalIdentifier
},
"onCreate" => %{
"externalId" => externalIdentifier,
"fullName" => fullName,
"shortName" =>
if name != nil do
name
else
nil
end,
"email" => %{
"email" => email,
"isVerified" => false
}
},
"onUpdate" => %{
"fullName" => %{
"value" => fullName
},
"shortName" =>
if name != nil do
%{"value" => name}
else
nil
end,
"email" => %{
"email" => email,
"isVerified" => true
},
"externalId" => %{
"value" => externalIdentifier
}
}
}
})
end
@customerByIdQuery "queries/getCustomerById.graphql" |> File.read!()
@spec getCustomerById(String.t()) :: {:ok, map()} | {:error, any()}
@doc """
If you already have the ID of a customer from within Plain or one of our other endpoints you can fetch more details about them using getCustomerById in the SDK.
These endpoints require the following permissions:
- `customer:read`
"""
def getCustomerById(customer_id) do
send_request(@customerByIdQuery, %{"customerId" => customer_id})
end
@spec send_request(String.t(), map()) :: {:ok, map()} | {:error, any()}
defp send_request(query, variables) do
req =
base_request()
|> Req.merge(
body:
Jason.encode!(%{
query: query,
variables: variables
})
)
|> Req.request()
case req do
{:ok, %Req.Response{status: 200, body: body}} ->
case Jason.decode(body) do
{:ok, %{"data" => data}} ->
{:ok, data}
{:error, reason} ->
{:error, reason}
end
{:ok, %Req.Response{status: 401}} ->
{:error, "Unauthorized"}
{:ok, %Req.Response{status: 403}} ->
{:error, "Forbidden"}
{:ok, %Req.Response{status: 500}} ->
{:error, "Internal server error"}
{:ok, %Req.Response{status: status}} ->
{:error, status}
{:error, reason} ->
{:error, reason}
end
end
defp base_request do
Req.new(
method: :post,
url: base_url(),
headers: [{"Content-Type", "application/json"}, {"Accept", "application/json"}],
auth: {:bearer, token()}
)
end
end