Skip to content

Repository files navigation

@m8t-jacob/allegro-sdk

CI npm version npm downloads bundle size license: MIT

A typed TypeScript/Node client for the Allegro REST API: OAuth2 authentication (client credentials, authorization code, automatic token refresh), browsing categories, reading your selling offers, searching the product catalog, and reading orders.

  • Strict TypeScript, ships dual ESM + CJS builds with .d.ts
  • Zero runtime dependencies — uses the global fetch (Node.js 20+), or an injected implementation via AllegroClientConfig.fetch
  • Tree-shakeable; import the whole package or a single subpath (/auth, /categories, /offers, /orders, /user)
  • Full OAuth2 support: Client Credentials, Authorization Code (with a helper to build the login URL and exchange the returned code), refresh tokens, and automatic retry-after-refresh on a 401 response
  • clientId/clientSecret sent as HTTP Basic auth on token requests, access tokens sent as Authorization: Bearer, never in a URL or logged
  • Every request has a configurable timeout; every failure mode (network error, timeout, non-2xx status, malformed JSON) is normalized to a single AllegroError type, with status/errors populated from the Allegro API's own { errors: [{ code, message, userMessage, path }] } error body when available
  • Zero real network calls in tests — the test suite mocks fetch, so CI runs deterministically offline

Install

npm install @m8t-jacob/allegro-sdk

Quickstart

Client Credentials (public resources: categories, product search)

import { AllegroClient } from '@m8t-jacob/allegro-sdk';

const client = new AllegroClient({
  clientId: process.env.ALLEGRO_CLIENT_ID!,
  clientSecret: process.env.ALLEGRO_CLIENT_SECRET!,
  sandbox: true, // omit or set to false for production
});

await client.getClientCredentialsToken();

const categories = await client.getCategories(); // top-level categories
const laptops = await client.getCategories('12345'); // children of category 12345

const products = await client.searchProducts({ phrase: 'laptop', limit: 10 });
console.log(products.totalCount, products.items[0]?.name);

Authorization Code (a specific Allegro account's offers/orders)

const client = new AllegroClient({
  clientId: process.env.ALLEGRO_CLIENT_ID!,
  clientSecret: process.env.ALLEGRO_CLIENT_SECRET!,
  sandbox: true,
  onTokenRefresh: (tokens) => {
    // Persist tokens.access_token / tokens.refresh_token, e.g. to your database.
    saveTokens(tokens);
  },
});

// 1. Redirect the user to Allegro's login/consent screen:
const authUrl = client.getAuthorizationUrl('https://your-app.example.com/callback', {
  scope: ['allegro:api:sale:offers:read', 'allegro:api:orders:read'],
});

// 2. After the user logs in, Allegro redirects back with a `code` query param.
//    Exchange it for tokens:
const tokens = await client.exchangeCodeForToken(code, 'https://your-app.example.com/callback');

// 3. Use the client — it's now authenticated as that user:
const offers = await client.getMyOffers({ publicationStatus: 'ACTIVE', limit: 25 });
const orders = await client.getCheckoutForms({ status: 'BOUGHT' });
const me = await client.getMe();

On any subsequent request, if the access token has expired, AllegroClient automatically calls refreshAccessToken (using the configured refreshToken) and retries the original request once — you don't need to handle 401s yourself as long as a refresh token is available. If you restore a session on startup, pass accessToken/refreshToken from storage directly instead of repeating the login flow:

const client = new AllegroClient({
  clientId: process.env.ALLEGRO_CLIENT_ID!,
  clientSecret: process.env.ALLEGRO_CLIENT_SECRET!,
  accessToken: savedTokens.access_token,
  refreshToken: savedTokens.refresh_token,
  onTokenRefresh: saveTokens,
});

You can also import a subpath if you only need one module, which keeps bundlers from pulling in the others (note these export plain functions taking an AllegroRequestContext/AuthConfig, not a pre-bound client — see Advanced: calling module functions directly):

import { getClientCredentialsToken } from '@m8t-jacob/allegro-sdk/auth';
import { getCategories } from '@m8t-jacob/allegro-sdk/categories';

API

AllegroClient

new AllegroClient({
  clientId: string;
  clientSecret: string;
  sandbox?: boolean;              // default: false (production)
  accessToken?: string;           // restore a previously obtained token
  refreshToken?: string;          // enables auto-refresh on 401 from the start
  timeoutMs?: number;             // default: 15000
  fetch?: typeof fetch;           // default: global fetch
  onTokenRefresh?: (tokens: TokenResponse) => void; // called after any token is obtained/refreshed
})
Method Description
getClientCredentialsToken(): Promise<TokenResponse> Obtains an app-only access token. No user login involved.
getAuthorizationUrl(redirectUri, opts?): string Builds the URL to redirect a user to for login/consent.
exchangeCodeForToken(code, redirectUri): Promise<TokenResponse> Exchanges an Authorization Code grant's code for user-scoped tokens.
refreshAccessToken(refreshToken?): Promise<TokenResponse> Refreshes the access token (defaults to the configured refresh token).
getCategories(parentId?): Promise<Category[]> Lists top-level categories, or the children of parentId.
getCategory(id): Promise<Category> Fetches a single category by id.
getCategoryParameters(categoryId): Promise<CategoryParameter[]> Fetches the listing attributes (parameters) for a category.
getMyOffers(params?): Promise<PaginatedResult<Offer>> Lists the authenticated user's selling offers.
getOffer(id): Promise<Offer> Fetches a single offer by id.
searchProducts(params?): Promise<PaginatedResult<Product>> Searches the public product catalog by phrase/category.
getCheckoutForms(params?): Promise<PaginatedResult<CheckoutForm>> Lists the authenticated seller's orders.
getCheckoutForm(id): Promise<CheckoutForm> Fetches a single order by id.
getMe(): Promise<AllegroUser> Fetches basic account info for the current access token.

getAuthorizationUrl/exchangeCodeForToken/getClientCredentialsToken/getMyOffers/getCheckoutForms/getMe require an Authorization Code user token; getCategories/getCategory/getCategoryParameters/searchProducts work with either grant type.

Categories (categories)

const topLevel = await client.getCategories();
const children = await client.getCategories('automotive-category-id');
const category = await client.getCategory('automotive-category-id');
const parameters = await client.getCategoryParameters('automotive-category-id');

Offers (offers)

await client.getMyOffers({
  phrase: 'iphone',
  publicationStatus: 'ACTIVE', // or 'INACTIVE', 'ENDED'
  offset: 0,
  limit: 20,
});

await client.searchProducts({ phrase: 'iphone', categoryId: '257', offset: 0, limit: 20 });

Orders (orders)

await client.getCheckoutForms({
  status: 'BOUGHT', // e.g. 'BOUGHT', 'FILLED_IN', 'READY_FOR_PROCESSING', 'CANCELLED'
  fulfillmentStatus: 'NEW', // e.g. 'NEW', 'PROCESSING', 'SENT'
  offset: 0,
  limit: 20,
});

const order = await client.getCheckoutForm('order-id');

Order creation/mutation (marking as shipped, cancellations) isn't in this release — see GOOD_FIRST_ISSUES.md.

Pagination

List endpoints (getMyOffers, searchProducts, getCheckoutForms) accept offset/limit and return:

interface PaginatedResult<T> {
  items: T[];
  count: number;      // items returned in this page
  totalCount: number;  // total items available
  offset: number;      // echoes the request's offset
  limit: number;       // echoes the request's limit
}

There is no built-in "fetch all pages" helper in this release — call the same method again with an incremented offset, using totalCount as the stop condition. See GOOD_FIRST_ISSUES.md for a tracked helper idea.

Errors

Every operation throws AllegroError for invalid input (checked before any network call), a non-2xx response, a network error, a timeout, or malformed JSON:

export class AllegroError extends Error {
  readonly status?: number;              // HTTP status, when applicable
  readonly errors?: AllegroErrorEntry[]; // the API's `errors` array, when available
}

interface AllegroErrorEntry {
  code?: string;
  message?: string;
  userMessage?: string; // human-readable, often in Polish
  path?: string;
}
try {
  await client.getOffer('does-not-exist');
} catch (error) {
  if (error instanceof AllegroError) {
    console.error(error.status, error.message, error.errors);
  }
}

OAuth token errors ({ error, error_description }, per RFC 6749 — a different shape than the REST API's { errors: [...] }) are also normalized to AllegroError, with a single synthesized errors entry.

Advanced: calling module functions directly

Every AllegroClient resource method delegates to a plain function exported from its module (getCategories, getMyOffers, getCheckoutForm, etc.), taking an AllegroRequestContext as the first argument instead of the AllegroClient class. The auth.ts functions similarly take an AuthConfig object ({ clientId, clientSecret, sandbox?, ... }) instead of a bound client. This is mostly useful for testing or building your own thin wrapper with custom token management; most users should just use AllegroClient.

Endpoints and API version

This package targets the Allegro REST API (vendor media type application/vnd.allegro.public.v1+json) at:

  • REST API production: https://api.allegro.pl
  • REST API sandbox: https://api.allegro.pl.allegrosandbox.pl
  • OAuth production: https://allegro.pl (/auth/oauth/token, /auth/oauth/authorize)
  • OAuth sandbox: https://allegro.pl.allegrosandbox.pl
Resource Endpoint(s)
Client Credentials token POST /auth/oauth/token (grant_type=client_credentials)
Authorization Code login GET /auth/oauth/authorize (response_type=code)
Authorization Code token exchange POST /auth/oauth/token (grant_type=authorization_code)
Refresh token POST /auth/oauth/token (grant_type=refresh_token)
Categories GET /sale/categories, GET /sale/categories/{id}
Category parameters GET /sale/categories/{id}/parameters
My offers GET /sale/offers, GET /sale/offers/{id}
Product search GET /sale/products
Orders GET /order/checkout-forms, GET /order/checkout-forms/{id}
Account info GET /me

Honest scope note: these endpoints and response shapes are modeled from Allegro's public REST API documentation (developer.allegro.pl) at the time of writing. Unlike the sibling inpost-shipx package (whose endpoints were confirmed by hand with curl against the live API), this package's endpoints were not independently verified against a live Allegro sandbox account before this release — see GOOD_FIRST_ISSUES.md for tracked verification work. If Allegro changes any of these endpoints or the error body shape, please open an issue.

This is not full coverage of the Allegro REST API — notably missing: offer creation/update, order fulfillment (marking as shipped), returns and disputes, billing/commission endpoints, and webhooks. See GOOD_FIRST_ISSUES.md for what's tracked.

🇵🇱 Po polsku

@m8t-jacob/allegro-sdk to typowany klient TS/Node dla REST API Allegro: uwierzytelnianie OAuth2 (client credentials, authorization code, automatyczne odświeżanie tokenu), przeglądanie kategorii, odczyt własnych ofert, wyszukiwanie w katalogu produktów oraz odczyt zamówień. Pakiet nie ma żadnych zależności uruchomieniowych — korzysta z globalnego fetch (Node.js 20+). Dane clientId/clientSecret są wysyłane wyłącznie w nagłówku Authorization: Basic przy żądaniach tokenu, a token dostępu w nagłówku Authorization: Bearer — nigdy w adresie URL i nigdy nie są logowane. Każde żądanie ma konfigurowalny timeout, a każdy rodzaj błędu jest ujednolicony do jednego typu AllegroError. Testy nie wykonują żadnych realnych zapytań sieciowych (mockowany fetch), dzięki czemu CI działa deterministycznie offline. Uwaga o zakresie: to nie jest pełne pokrycie REST API Allegro (patrz GOOD_FIRST_ISSUES.md po angielsku) — brakuje m.in. tworzenia/edycji ofert, realizacji zamówień, zwrotów, rozliczeń i webhooków.

Contributing

Contributions are welcome! See CONTRIBUTING.md for the development workflow and GOOD_FIRST_ISSUES.md for ideas if you're looking for a place to start. This project follows the Contributor Covenant.

License

MIT © 2026 Jakub Jagiełło

About

Typed TypeScript client for the Allegro REST API: OAuth2 with auto-refresh, categories, offers, orders. Zero dependencies.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages