Commit Graph

7 Commits

Author SHA1 Message Date
ignacionelson 5c00d189e4 Deletions can start a Zap after all
I said they could not, in the guide, the Zapier page and the changelog.
That was carried over from the limitation of polling a list, where a
deleted row stops being returned and nothing marks the moment it went. It
was never true of the activity endpoint: file.deleted is recorded like
any other action, so ?action[]=file.deleted works today.

Checked with a test rather than the enum, which turned up the shape a
caller needs: a deletion entry has no subject, because the row is gone by
the time the entry is written, so the name is snapshotted into
context.name instead. Reading subject.name there gets you null.
2026-08-25 18:51:05 -03:00
ignacionelson 7646e99f33 Add an activity endpoint, so an integration can react rather than poll for shape
Every list in /api/v1 answers "what is there now". Nothing answered
"what happened", and for the two events people most want to act on there
was nowhere to look at all.

Sharing a file writes an assignment row and never touches the file, so no
amount of polling /files?updated_since= will ever show a share. A
download is recorded only in the activity log. So the most requested
automations for a file-sharing product — tell me when a client gets a
file, tell me when they open it — were not possible to build.

GET /api/v1/activity is one feed rather than one endpoint per event,
because the log already records every one of them and a caller filtering
by action gets whatever the application grows later without waiting for
us to expose it.

It reuses what already exists: view_actions_log is the permission the
activity screen uses, and ActivityLogScope narrows the rows the same way,
so a staff member limited to their assigned clients cannot read the whole
installation's log through a token when the screen would not show it.

Two deliberate limits. Class names never reach the wire — subject.type is
a stable public string, or moving a model between namespaces would be a
breaking change to a frozen contract. And no ip_address, though the
column exists and the screen shows it: a person looking at a log has
decided to look, where an integration streams every row to somebody
else's servers by default.

PollingQuery grew an optional column so it can walk a table that is
appended to rather than edited. The parameter stays updated_since
everywhere, because on an append-only log the two timestamps are the same
thing and one shape learned once is worth more than a second name.
2026-08-25 18:44:51 -03:00
ignacionelson 3f27c8dbf8 Correct the Zapier guide on token expiry, and say which Zapier plan it needs
Two things the guide got wrong, both of which would waste somebody's
afternoon.

It said tokens max out at a year and left it there. There is a "Never
expires" option on the token screen, and for an unattended integration
that is usually the right choice — the guide now says so, along with why
it is off by default and what to do instead if you keep an expiry.

And everything in it uses Webhooks by Zapier, which Zapier includes only
from its Professional plan up. Somebody on the free plan would follow the
whole page and then find they cannot add the step. That belongs at the
top, not in a support ticket.
2026-08-25 18:35:46 -03:00
ignacionelson 7059ee293a Add a Zapier guide to the API documentation page
The API has had everything Zapier needs since it shipped — a bearer
token, an auth-test endpoint at /me, and list endpoints that return
newest-first with a stable id, which is exactly the shape a polling
trigger wants. What was missing was anyone saying so.

This is written for somebody wiring up a Zap, not for somebody writing
code, which is why it is a second document rather than a section of the
guide. Same reason it renders in-app rather than linking to GitHub: the
installations most likely to need it are the ones least likely to have
outbound internet access.

It says out loud the two things that will otherwise be discovered the
hard way — a token expires within a year and nothing renews it, and a
deletion cannot start a Zap because polling cannot see one.
2026-08-25 01:08:09 -03:00
denkfabrik-li 6a8a287984 Name the tab Outgoing email, not Sending
Discussion feedback: in ProjectSend "sending" can just as well mean
files. Outgoing email is unambiguous and the established name for this
screen elsewhere (GitLab, Jira, Moodle all call it that).
2026-08-24 06:58:28 +02:00
denkfabrik-li 19d34ef38b Document the OAuth mail providers, linked from the settings screen
A step-by-step guide (docs/email-oauth.md, same shape as the API
guide, whitelisted alongside it) through both vendor consoles: the
Entra app registration with its three account-type choices and what
each means for the tenant field, and the Google Cloud client with its
consent screen, test users and the testing-status 7-day refresh-token
expiry. The troubleshooting entries are errors actually hit while
building this — including Graph's ErrorQuotaExceeded, whose message
text hides that the mailbox may simply be full.

The Sending tab links to the guide right where an admin picks an
OAuth provider, via the shared links.source origin.
2026-08-23 22:46:25 +02:00
ignacionelson 6e47d76ba6 ProjectSend 2.0.0
Client file sharing, rebuilt from the ground up: a private area per
client, resumable uploads, folders, groups and categories, sharing with
expiry dates and download limits, comments, file versions, an activity
log, a REST API, and sixteen languages.

This repository begins here. ProjectSend 2 was developed privately, and
that development history is not published — the previous generation
remains available, with its own history, at projectsend/legacy.

Free software under the GNU General Public License v2, or (at your
option) any later version.
2026-08-14 01:38:12 -03:00