npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@taskmagic/apps-simplero

v0.0.2

Published

Contacts, tags, mailing lists, course access and orders in [Simplero](https://simplero.com) — the all-in-one courses, membership, email marketing and e-commerce platform.

Readme

Simplero

Contacts, tags, mailing lists, course access and orders in Simplero — the all-in-one courses, membership, email marketing and e-commerce platform.

API docs: the product serves its own OpenAPI 3.1 document at https://simplero.com/api/v2/docs/openapi.json — 614 paths and 151 schemas, and the authoritative reference for this piece. (The human-facing docs page is a JavaScript shell that renders that same document.)

The API is REST under https://simplero.com, every path versioned as /api/v2/..., and authenticated with an X-API-Key header. /api/v1 is deprecated and is not used here.

  • Actions: List Contacts, Create Contact, Update Contact, Add Tag To Contact, Remove Tag From Contact, Subscribe Contact To List, Unsubscribe Contact From List, Grant Course Access, Revoke Course Access, List Purchases, List Products, List Tags, List Lists.
  • Triggers: New Contact (polling), New Purchase (polling), New List Subscription (polling).

Connection: in Simplero go to Settings → Integrations → Create New API Key, then use the copy button next to the new key and paste it into the connection. A Simplero API key carries full admin rights over the account, so create a separate key for TaskMagic rather than reusing an existing one — that way it can be revoked on its own. The Simplero admin is account-scoped and behind a login, so there is no stable public URL to link to; use the menu path above.

Notes

  • The User-Agent header is enforced, and it is checked before authentication. Simplero requires a User-Agent containing an app name and a contact email. A missing or empty one comes back as HTTP 400 {"error":"Incorrect User-Agent"} — verified live — which looks nothing like the real cause, and it fires before the API key is even examined. The piece hardcodes TaskMagic ([email protected]) in its shared request helper so no call site can omit it.
  • Identifiers are ambiguous, and this needs confirming against a live account. Every {id} path parameter in the spec is typed integer, yet of the 151 schemas only BuilderDocNode declares an id property at all — Customer, Purchase, Subscription, Tag and List expose a string token instead, and Product and Course declare neither. Because the spec contradicts itself, the Contact ID inputs are free text and pass through whatever you give them verbatim: try the numeric ID from the contact's admin URL first, and the token from List Contacts if that 404s. The Tag / List / Course / Product dropdowns use id when the live response actually returns one and fall back to token; a record that carries neither is left out of the dropdown rather than offered with an empty value, so if the Course or Product dropdown comes up empty against a live account that is this same ambiguity and is worth reporting.
  • Polling triggers only — there is no webhook API. Simplero v2 defines no /webhooks paths and no outgoing-webhook schema. POST /api/v2/customers/{id}/actions/webhook only fires a webhook record that already exists, identified by an outgoing_webhook_id that nothing in the API creates or lists, so there is nothing for a trigger to auto-register or to tear down. If you want push delivery, configure a Simplero Trigger by hand in the Simplero admin to POST to a TaskMagic Catch Hook URL; that is a manual setup on both sides, not something this piece can wire up for you.
  • Nothing can be sorted. Not one of the 614 documented paths accepts sort, order, direction or sort_by, so a poll cannot ask for newest-first. Each trigger instead re-reads a timestamp window on every poll (created_at for New Contact and New List Subscription, purchased_at for New Purchase) and lets the timestamp comparison decide what is new. Rows are also collapsed on token within a poll, because paging an unsorted list that is being written to can hand back the same row on two different pages. Each poll reads at most 5 pages of 100, and looks back at most 30 days — without that clamp a trigger that found nothing would widen its window by a day every day and drift permanently past the page cap. A trigger's dedupe timestamp is always the same field its window filters on; keying the two on different fields makes a row fire twice as soon as the second field catches up.
  • Date filters have day granularity, in the account's timezone. DateFilter.from / .to are format: date, and the API does not report which timezone the account interprets them in. The triggers therefore widen their window by a day at each end — enough to cover every offset from UTC-12 to UTC+14 — and rely on the exact timestamp comparison to narrow it back down.
  • New Purchase watches purchased_at, New List Subscription watches created_at. Simplero writes a purchase row while the order is still being taken, so created_at would also fire on carts that were never paid for. Conversely a double-opt-in list creates the subscription row at signup but leaves first_activated_at null until the confirmation link is clicked, so filtering on that field would silently never fire for those lists.
  • Filters are deepObject, not JSON. They go on the wire as ?created_at[preset]=custom&created_at[from]=2026-07-01 and ?email[op]=equals&email[value]=…; the request helper flattens nested objects into those bracketed names. List Contacts exposes the useful subset of roughly eighty available filters — email, first names, last name, status, tag, list, product, created and updated — rather than burying them among UTM attribution, funnel steps, countdown timers and deal pipelines.
  • Pagination is 1-indexed (page, per_page, 1–100, default 20) — v1 was 0-indexed, so a ported flow that starts at page 0 will silently misbehave. List responses come back as { "data": [...], "pagination": { page, per_page, total, total_pages } }; the actions return the rows and the paginator separately.
  • Error shapes are inconsistent. Most failures answer {"error":"..."} (a string), while validation failures answer {"errors":["...","..."]} (an array, plural key). The error parser reads both; a 422 would otherwise surface with an empty message. Only 200, 401, 404 and 422 are documented as responses, plus the undocumented 400 for the User-Agent check.
  • Rate limits are not documented. No RateLimit-* and no Retry-After header was observed on any response, so there is no published budget to respect and no server-supplied delay to honour. The request helper retries 408/429/5xx and network failures up to three times with exponential backoff (500 ms, 1 s), and every request has a 30 second timeout. Only GET is retried on all of those: a lost response is indistinguishable from a write the server accepted, so the write verbs are replayed only on 429, the one status that means the request was never processed.
  • Action verbs are checked, not trusted. Simplero's /actions/... endpoints answer HTTP 200 with {"data":{"success":false,"message":"..."}} when they decline to do the work. The tag, list-subscription and course actions fail the step in that case rather than reporting success.
  • No custom API call action. A passthrough would hand this connection's key — which has full admin rights over the Simplero account — to any URL a flow supplied.
  • Deliberately not built: Simplero exposes 100+ further /customers/{id}/actions/... verbs (automations, countdown timers, deals, events, credits, badges, SMS, Mailchimp and Meta audience sync, and more) plus create/update endpoints for most of its 68 top-level resources. Only the contact, tag, list, course and commerce surface people actually automate is shipped here.