Plan limits
What each plan allows, what the API answers when a limit is reached, and how
to get past it. The per-second request rate of the Event API is a separate
limit, documented with the 429 answers in
the Errors section of the Event API reference.
Limits by plan
The self-service plans and the 14-day trial. A new organization normally
starts on the trial once its email is verified. Each organization, and each
email domain (each address, for free email providers), gets one trial: when
it was already used, the organization starts on Developer and
GET /api/v1/billing/me says why in trial_blocked_reason.
| Limit | Developer | Starter | Pro | Scale | Trial |
|---|---|---|---|---|---|
| Connectors | 1 | 1 | 5 | 15 | 15 |
| Event sources | 4 | 4 | 5 | 15 | 15 |
| Events per month | 2,000 | 25,000 | 75,000 | 400,000 | 20,000 |
| Team seats | 1 | 5 | 5 | 5 | 5 |
| HubSpot portals | 1 | 1 | 1 | 3 | 3 |
| Custom object types | none | none | none | 5 | 5 |
| AI assistant sessions per day | no limit | no limit | no limit | no limit | 10 |
| Plugins | no | no | no | no | no |
The tier field of every limit response names the plan: free for
Developer, then starter, pro, scale and trial.
“Connected systems” means two different things depending on where you
read it. On the pricing page it is the Connectors row. In the dashboard’s
usage bar and in the event_source_limit_reached message it is the Event
sources row.
Enterprise and Custom-Dedicated. Limits, plugins and SLA reporting are
set in the contract. Contact sales through the contact form on
plugsync.com . On Enterprise, tier is
enterprise.
Limits agreed for your organization apply in place of the plan’s own:
GET /api/v1/billing/me always returns the ones in force.
When the trial ends, or a paid subscription is cancelled, the organization moves to Developer on its own. Nothing is deleted: connectors, sources, members and portals over the new limits keep working and stay editable, but nothing more of that kind can be added until the organization is back under the limit or upgrades.
Where you stand
GET /api/v1/billing/me returns the plan and every counter, and accepts an
organization API key as well as a signed-in session. The dashboard, under
Settings, Billing, shows bars for events, event sources (labelled “Connected
systems”), seats, HubSpot portals and custom object types; the connector
count is only in the API.
| Field | Meaning |
|---|---|
tier | The current plan. |
connectors_used, connectors_limit | Connectors of the organization. |
event_sources_used, event_sources_limit | Event sources, counted across every connector. |
events_used_this_period, events_limit, period_resets_at | Events counted this calendar month (UTC) and when the count restarts. |
seats_used, seats_limit | Members plus open invitations (an expired invitation no longer counts). |
portals_used, portals_limit | HubSpot portals connected. |
custom_object_types_used, custom_object_types_limit, custom_objects_enabled | Distinct custom object types in the published configs, and whether the plan includes custom objects. |
upgrade_url | Where to change plan. null when there is nothing to upgrade to on your own. |
A null limit means the plan has no limit on it.
What a limit answers
A request that would go over a limit, or that needs a feature the plan does
not include, answers 402 Payment Required and changes nothing. The body
always has the same shape:
{
"detail": {
"error": "seat_limit_reached",
"tier": "starter",
"message": "Your starter plan allows 5 team members. Upgrade to invite more.",
"upgrade_url": "https://app.plugsync.com/settings/billing",
"limit": 5,
"usage": 5
}
}| Field | Meaning |
|---|---|
error | The code: match on this, never on message. |
tier | The organization’s plan when the request was refused. |
message | An explanation for a person. |
upgrade_url | The dashboard billing page, where an owner changes plan. |
limit, usage | The limit and the current count, on the limits that count something. |
custom_object_types | On the custom object codes only: the custom object types the draft declares. |
The monthly event quota is the exception: it answers 429, described in
Events per month.
| Limit | Status | error |
|---|---|---|
| Connectors | 402 | connector_limit_reached |
| Event sources | 402 | event_source_limit_reached |
| Events per month | 429 | quota_exceeded |
| Team seats | 402 | seat_limit_reached |
| HubSpot portals | 402 | portal_limit_reached |
| Custom objects | 402 | custom_objects_not_allowed, custom_object_type_limit_reached |
| AI assistant sessions | 402 | agent_session_daily_limit_reached |
| Plugins and test connectors | 402 | plugin_system_not_allowed |
| SLA reporting | 402 | sla_monitoring_not_available |
Each limit
Connectors
Checked when a connector is created: POST /api/connectors and
POST /api/v1/connectors/from-template/{template_id}. Answers
connector_limit_reached once the organization has as many connectors as
its plan allows.
To get past it: delete a connector you no longer use
(DELETE /api/connectors/{id}), or upgrade.
Event sources
Every source of every connector counts once: webhook, HubSpot, polling, scheduled and file sources alike. A source counts from the publish that creates it. The limit is checked wherever sources are added:
POST /api/connectors/{id}/sources, as an early warning when the source is declared in the draft;POST /api/connectors/{id}/publish, on the sources the publish would add;POST /api/v1/connectors/from-template/{template_id}, on every source the template declares, all at once, before the connector is created.
Only the net count matters: a publish that adds one source and removes another stays within the limit. Editing, renaming or deleting an existing source is never refused, even when the organization is over its limit.
Answers event_source_limit_reached. To get past it:
- delete a source you no longer use;
- reuse a source instead of adding one:
PATCHit in place to point it somewhere else, or declare the replacement and remove the old source in the same draft so one publish does both; - upgrade.
Deleting a source while the organization is over its limit answers
409 event_source_delete_confirmation_required, because one deletion would
not free a slot to create another. To delete it anyway, resend
DELETE /api/connectors/{id}/sources/{name}?confirm=true.
Events per month
Every event processed for the organization counts: each entity accepted by
POST /api/v1/events, each row a bulk import writes, and each event from a
webhook, HubSpot, polling, scheduled or file source once it is processed.
The count restarts on the first day of each calendar month, UTC.
The limit refuses the events you send. Once the month’s events are used up,
POST /api/v1/events answers 429 with error: quota_exceeded, and a bulk
import is refused as a whole when its rows do not fit in what is left of the
month. The body carries events_used_this_period, tier, upgrade_url and
period_resets_at; the full body is in
the Errors section of the Event API reference.
The legacy-compatible ingress answers 429 in its own shape,
{"result": "error", "message": "Monthly event quota exceeded"}, when the
call’s events do not fit: see
its responses.
Events from the sources plugsync reads on its own count towards the same
total but are not refused.
To get past it: upgrade, or wait for period_resets_at.
Team seats
A seat is a member or an open invitation. An invitation stops holding a seat once it is accepted (its seat becomes the new member’s), revoked, or expired (after 7 days).
Checked when an owner invites someone (POST /api/orgs/{org_id}/invitations):
the invitation needs a free seat. Checked again when the invitation is
accepted (POST /api/invitations/{token}/accept): the invitation already holds
its seat, so accepting only fails when the other members and open invitations
already fill the plan, for example after a downgrade. Inviting up to the limit
and having everyone accept fills every seat of the plan. Answers
seat_limit_reached.
To get past it: revoke open invitations
(DELETE /api/orgs/{org_id}/invitations/{invitation_id}), remove a member,
or upgrade. See Managing the team.
HubSpot portals
Checked when a HubSpot portal the organization has not connected before is connected. Reconnecting a portal that is already connected never counts.
- Attaching a HubSpot app install to an organization
(
POST /api/v1/auth/hubspot/install/{token}/attach) answers402 portal_limit_reached. - The browser connect flow returns to the dashboard and shows the same
error there instead of a
402.
To get past it: disconnect a portal you no longer use by deleting its
HubSpot credential (DELETE /api/credentials/{id}), or upgrade.
Custom objects
A custom object type is any object_type of an entity other than the
standard ones: contacts, companies, deals, tickets, products and
line_items (singular forms count as the same type). Checked on every draft write: PUT and PATCH
on /api/connectors/{id}/draft, the entity writes, reset and discard, and
the AI assistant’s edits.
custom_objects_not_allowed: the plan does not include custom objects (Developer, Starter, Pro) and the draft declares one.custom_object_type_limit_reached: the draft declares more distinct custom object types than the plan allows. The count is per connector.
Both list the types found in custom_object_types. To get past it: remove
the entities that target custom objects from the draft, or upgrade.
AI assistant sessions
Trial organizations only. A trial organization can start 10 new assistant sessions per day (UTC). A new session starts with:
POST /api/agent/chatwithout asession_id;POST /api/agent/sessions/{session_id}/resume, which opens a new session on the connector of a finished one;POST /api/agent/resume-connector/{connector_id}, when the connector has no open session orforce_new=trueis passed.
Continuing an open session does not count. Answers
agent_session_daily_limit_reached.
Within one trial session the assistant makes up to 25 tool calls. Past that it ends its turn with a message saying so, not with an error: start a new session to continue.
To get past it: upgrade to a paid plan, or wait for the next day (UTC).
Plugins and test connectors
Plugins are included on Enterprise and Custom-Dedicated. On the other plans
POST /api/plugins, POST /api/plugins/{id}/push and
POST /api/plugins/{id}/promote answer plugin_system_not_allowed, and so
does POST /api/connectors for a connector with mode: "test". A
test-mode connector needs a signed-in user: with an organization API key
that request answers 403 api_key_cannot_create_test_connector first,
whatever the plan. Listing,
reading, invoking and reading the logs of existing plugins are not limited.
See Plugins.
To get past it: contact sales.
SLA reporting
GET /api/connectors/{id}/sla is included on Enterprise and
Custom-Dedicated and answers sla_monitoring_not_available on the other
plans.
To get past it: contact sales.
Changing plan
An owner changes plan from the dashboard billing page, the page every
upgrade_url points to. Starter, Pro and Scale are bought there with a card;
Enterprise and Custom-Dedicated go through sales. Checkout and plan changes
need a signed-in owner: an organization API key gets
403 user_auth_required (see
Actions that need a signed-in user).
The new limits apply as soon as the change is confirmed.