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 viaAllegroClientConfig.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
401response clientId/clientSecretsent as HTTP Basic auth on token requests, access tokens sent asAuthorization: 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
AllegroErrortype, withstatus/errorspopulated 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
npm install @m8t-jacob/allegro-sdkimport { 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);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';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.
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');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 });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.
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.
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.
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.
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.
@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.
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.
MIT © 2026 Jakub Jagiełło