@undernouzen/ay-payments-sdk
v1.4.1
Published
TypeScript SDK for AY Payments API integrations
Downloads
1,160
Maintainers
Readme
AY Payments SDK
TypeScript/JavaScript SDK for the AY Payments API.
Full docs: https://aypayments.undernouzen.com.br/docs/
Install
npm install @undernouzen/ay-payments-sdkpnpm add @undernouzen/ay-payments-sdkCreate a client
import { createAYPaymentsClient } from "@undernouzen/ay-payments-sdk";
const ay = createAYPaymentsClient({
baseUrl: "https://aypayments.undernouzen.com.br",
apiKey: process.env.AYP_API_KEY,
});The default API base is:
https://aypayments.undernouzen.com.br/api/v1You can also pass the exact API URL:
const ay = createAYPaymentsClient({
apiUrl: "http://localhost:3489/api/v1",
apiKey: "ayp_secret",
});Authentication
Default:
Authorization: Bearer ayp_secretUse x-api-key instead:
const ay = createAYPaymentsClient({
apiKey: "ayp_secret",
authHeader: "x-api-key",
});Send the raw key in Authorization:
const ay = createAYPaymentsClient({
apiKey: "ayp_secret",
authorizationPrefix: false,
});The client can be created without an API key. Protected routes will then depend on session cookies or return an API auth error.
Error handling
Mapped SDK methods return ApiResult<T>, which is either the expected response or an ErrorResponse.
import { createAYPaymentsClient, isApiError } from "@undernouzen/ay-payments-sdk";
const ay = createAYPaymentsClient({ apiKey: "ayp_secret" });
const result = await ay.projects.accounts.list("project-id-or-external-id");
if (isApiError(result)) {
console.log(result.code, result.error);
return;
}
console.log(result.accounts);Error shapes:
type ErrorResponse = CommunError | ContextError | ExternalProviderError;All API errors include a stable code field together with error. When the API cannot map a more specific code, it returns error.unmapped.
Versioning
v1 is the default.
await ay.v1.projects.list();Convenience aliases point to v1:
await ay.projects.list();
await ay.products.listByProject("project-id");
await ay.checkouts.create(payload);Lists and queries
List methods support the old pagination format:
await ay.products.list({ page: 1, limit: 20 });They also support richer options:
await ay.products.list({
pagination: { page: 1, limit: 20 },
reverse: true,
orderBy: "createdAt",
order: "desc",
});Query methods keep the old format:
await ay.products.query({ name: "Cargo VIP" }, { page: 1, limit: 20 });And can receive query options for partial or exact matching:
await ay.products.query(
{ name: "vip" },
{
pagination: { page: 1, limit: 20 },
queryMode: "like",
reverse: true,
orderBy: "createdAt",
},
);You can also send the wrapped object directly:
await ay.orders.query({
query: { status: "paid" },
pagination: { page: 1, limit: 50 },
options: {
matchMode: "exact",
orderBy: "createdAt",
order: "desc",
},
});Raw requests
Use raw or the exposed Axios instance for endpoints not mapped yet.
const result = await ay.raw<{ ok: boolean }>({
method: "GET",
url: "/projects",
});const response = await ay.api.get("/projects");Projects
const result = await ay.projects.create({
externalId: "832320430277918720",
name: "Vagalumes",
webhookUrl: "https://guildbuilders.example.com/webhooks/aypayments",
metadata: {
guildId: "832320430277918720",
},
});
if (!isApiError(result)) {
console.log(result.project.id, result.created);
}Connected accounts
Generate an OAuth URL:
const oauth = await ay.projects.accounts.oauth({
projectId: "832320430277918720",
provider: "mercadopago",
name: "Conta principal",
redirectUrl: "https://guildbuilders.example.com/connect/result",
});
if (!isApiError(oauth)) {
console.log(oauth.authorizationUrl);
}List connected accounts:
const accounts = await ay.projects.accounts.list("832320430277918720");
if (!isApiError(accounts)) {
console.log(accounts.accounts);
}Public connected account responses never expose accessToken or refreshToken.
Products
Products use value. Product routes do not calculate platform commission; commission is calculated by checkout routes.
const product = await ay.products.create("832320430277918720", {
connectedAccountId: "330692399",
name: "Cargo VIP",
value: 19.9,
icon: "https://cdn.example.com/vip.png",
description: "Acesso VIP no Discord",
fees: [
{
name: "Taxa operacional",
kind: "fixed",
value: 1.5,
payer: "customer",
active: true,
},
],
});Checkouts
Calculate totals without creating an order/payment:
const calculation = await ay.checkouts.calculate({
items: [{ productId: "product-id", quantity: 1 }],
customer: {
email: "[email protected]",
name: "Cliente Teste",
},
currency: "BRL",
});Create a real checkout:
const checkout = await ay.checkouts.create({
paymentMethod: "pix",
items: [{ productId: "product-id", quantity: 1 }],
customer: {
email: "[email protected]",
name: "Cliente Teste",
documentType: "CPF",
document: "00000000000",
},
externalReference: "guild-832320430277918720-user-123",
webhookUrl: "https://guildbuilders.example.com/webhooks/orders",
metadata: {
guildId: "832320430277918720",
discordUserId: "123456789",
},
});Custom checkout without a registered product:
const checkout = await ay.checkouts.create({
projectId: "832320430277918720",
accountId: "330692399",
paymentMethod: "checkout",
items: [
{
name: "Cargo VIP",
amount: 19.9,
quantity: 1,
},
],
customer: {
email: "[email protected]",
name: "Cliente Teste",
},
});Typed imports
Everything is also available from types:
import type {
AyPaymentsCreateProjectPayload,
AyPaymentsCreateCheckoutResponse,
ErrorResponse,
} from "@undernouzen/ay-payments-sdk/types";Module-specific imports are supported:
import type { AyPaymentsCheckoutPayload } from "@undernouzen/ay-payments-sdk/modules/checkouts.types";
import { isApiError } from "@undernouzen/ay-payments-sdk/errors";