Tutorial

Sharing with a team

Instead of listing names on every document, make a team once and share with the team. Someone joins, they get what the team has. Someone leaves, they lose it everywhere β€” in one action, not a search through documents.

πŸ–₯️ Prefer a screen? Use the Teams page. Create teams, add and remove members, and see what each team can read β€” no curl needed. The composer offers your teams whenever a share is account-mode, and the Links page edits a live share’s teams. Everything below shows the same operations through the API and an AI assistant; each response was captured from pitchstation.ai, not written by hand.

Β§01The idea in one picture

A share points at a team; the team holds the people DOCUMENTS Q3 planPricing deckMSA draft ONE TEAM @you/design the shares point HERE PEOPLE yousimonruanyanglee ← added today change the middle box once, and all three documents follow β€” that is the whole feature yanglee joined after every document was shared, and can read all three. Remove them and all three close at once.

Β§02Before you start: a member is an account

A team member is a PitchStation account, not an email address on a list. There is no way to check that a stranger controls an address, so an address alone cannot let someone in.

Two ways in:

πŸ’‘ Why confirmation matters: only a confirmed address identifies a person. An invitation therefore completes only for an account whose verified email matches the invited address β€” forwarding the invitation email transfers nothing.

Β§03Do it in four steps

1Make the team

curl -X POST https://pitchstation.ai/api/teams \
  -H "Authorization: Bearer $PITCHSTATION_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"handle":"design","name":"Design team"}'
response
{ "success": true,
  "team": { "id": 2,
             "ref": "@leo_lin/design",   ← how anyone names it unambiguously
             "members": 1,              ← you, automatically
             "yourRole": "owner" } }

The handle (design) is what you type. The ref (@leo_lin/design) is what you use when a plain handle would be ambiguous β€” see Β§05.

2Add the people

# by email β€” the usual case
-d '{"email":"simon@example.com"}'

# or by username, if you know it
-d '{"username":"simonruan"}'
curl -X POST https://pitchstation.ai/api/teams/2/members \
  -H "Authorization: Bearer $PITCHSTATION_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"username":"simonruan"}'
response
{ "success": true,
  "granted": 0,
  "note": "This team has no documents yet." }

If they have not signed up yet you get a clear refusal rather than a silent no-op:

no account
{ "code": "USER_NOT_FOUND",
  "error": "No account for \"nobody@example.com\". A team member must
            already have an account: ask them to sign up at
            /signup.html, then add them." }

3Share a document with the team

curl -X POST https://pitchstation.ai/api/share \
  -H "Authorization: Bearer $PITCHSTATION_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"title":"Q3 plan", "access":"account",
       "htmlContent":"…",
       "teams":["design"]}'
response
{ "slug": "QeexQIP5",
  "teams": { "teams": [ { "ref": "@leo_lin/design", "members": 2 } ] } }

Everyone on the team is emailed automatically β€” they get the link, and it opens once they sign in. Nobody else's does. (Β§08 covers exactly when mail is and is not sent.)

βœ… access: "account" matters. A team member has to sign in for PitchStation to know they are one. If you leave it as a public link, anyone with the URL gets in and the team adds nothing.

4Add someone later β€” and see what it grants

This is the part worth understanding before you do it. Adding a person gives them everything the team already has, not just what you share from now on. The response tells you the number:

adding yanglee, after the Q3 plan was shared
{ "success": true,
  "granted": 1,
  "note": "That also gives them access to 1 document already
            shared with this team." }

That is the intended behaviour β€” it is what "share with the team" means β€” but it is a surprise the first time, so the count is in the response rather than something to discover later.

Β§04Opening a document you already shared privately

You do not have to republish. Widen it in place and the link, password, analytics and comments all carry forward:

curl -X PATCH https://pitchstation.ai/api/share/<slug>/access \
  -H "Authorization: Bearer $PITCHSTATION_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"addTeams":["design"]}'
response β€” a link-mode share being widened
{ "promoted": { "from": "link", "to": "account",
                "note": "a team member must sign in to be recognised as one" },
  "grantedTo": 2,
  "note": "This document is now open to 2 more people." }

Going the other way needs no ceremony β€” {"removeTeams":["design"]} takes it back immediately.

Β§05When two teams have the same name

You can be in your own design team and a client's design team at the same time. When you type just design, PitchStation refuses and asks which β€” it does not pick one:

409 β€” nothing was shared
{ "code": "TEAM_AMBIGUOUS",
  "error": "\"design\" matches 2 teams. Name one exactly β€” nothing was shared.",
  "candidates": [
    { "ref": "@leo_lin/design", "members": 1, "yourRole": "admin"  },
    { "ref": "@bob/design",     "members": 2, "yourRole": "member" } ] }

Retry with the one you meant β€” "teams":["@bob/design"] or "teamIds":[3] β€” and it goes through.

🚨 Nothing partial ever happens. If you name three teams and one is ambiguous, none are attached and no document is published. A document that went to the wrong team cannot be recalled, so a clean failure beats a half-success.

Β§06What happens when someone leaves

You do thisWhat happens
Remove them from the teamAccess ends immediately, on every document the team granted. One action, not a search.
Archive the teamEvery document it opened closes. Nothing is deleted; un-archiving restores access exactly.
Their commentsStay. Deleting them would rewrite a discussion and orphan the replies to it.
The documentsUntouched. Removing a person changes who can read; it never changes what is there.

This is the reason to use teams at all. Offboarding somebody becomes one call instead of remembering every document they were named on.

Β§07Asking an assistant instead

If you have PitchStation connected to Claude Code, Codex or another assistant, say what you want:

"Make a team called design, add simon@example.com, and share
 the Q3 plan with it."
⚠️ An assistant will never resolve an ambiguous team name for you. If two teams match, it must show you both and stop. Choosing on your behalf would be exactly the mistake the refusal exists to prevent β€” the same rule as never deciding who signs a contract.

Β§08Who gets told, and when

Sharing something with a team emails the team. Changing who can reach a document you already shared does not, unless you ask.

What you doWho gets an email
Publish with teams:Every member, automatically. Putting a document in front of a team is telling them to read it.
Widen an existing share β€” PATCH /accessNobody, unless you add "notify": true. Widening is often just tidying up an allowlist, and mail nobody needs is mail everybody learns to ignore.
Add someone to a teamThe new member β€” one email listing what the team grants them (retroactive access someone can't see is access they don't have). Pass "notify": false to skip; their own notification preference always wins.
Invite someone without an accountThe invitee β€” an invitation with your quoted note and a signup link. When they sign up and confirm the address they join automatically, get the document list, and the inviter gets a "they joined" email.
Remove someoneNobody. Their access simply ends.
Send it again β€” POST /notifyWhoever you name: members, teams, viewers, recipients, owner. There is no β€œeveryone” default β€” a resend that reaches more people than you pictured is worse than one that reaches too few.
# the miss most people hit: widened without notify, and now want to tell them
curl -X POST https://pitchstation.ai/api/share/<slug>/notify \
  -H "Authorization: Bearer $PITCHSTATION_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"to":"members"}'          # or ["members","owner"]
# announce a document the team can already reach β€” same URL, same analytics
curl -X PATCH https://pitchstation.ai/api/share/<slug>/access \
  -H "Authorization: Bearer $PITCHSTATION_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"addTeams":["aip"],"notify":true}'
response
{ "grantedTo": 2,
  "notified": ["yanglee@mobileinteractive.com"] }

Two things it will not do: it never emails you unless you ask for owner, and it never re-sends a password β€” the password is stored hashed and cannot be recovered, so pass it on yourself. The response says so when the share has one.

🌐 Each member is emailed in their own language. A member who has set a Reading language in Profile β†’ Reading language gets the notification in it β€” one share to a mixed team sends one email per language (nine supported, δΈ­ζ–‡ included). The document title and your name stay exactly as you wrote them. No preference set means English mail, so tell new teammates the setting exists.

Widening without notify now tells you it stayed quiet, rather than looking like a notification that failed:

response
{ "notified": [],
  "notifyNote": "Nobody was emailed. Pass \"notify\": true to tell the 1 member,
                  or POST /api/share/<slug>/notify later." }
πŸ’‘ Anyone can turn these off. A member who has switched share-received emails off in their profile stays on the team and keeps their access β€” they just stop getting the mail. Their preference wins over your notify.

Β§09Things worth knowing

Β§10Not built yet

PitchStation Β· Sharing with a team Β· updated 2026-08-29 (invitations, roles, leave) Β· Every response above was captured from the live API
Related: sending a contract for signature Β· reviewing a shared document Β· tutorials