Guide
Team: people and synthetic accounts
People and synthetic accounts
Team in the sidebar (owners only) has two tabs:
| People | Synthetic accounts | |
|---|---|---|
| Who | Your colleagues, each with their own account and password, their own two-factor authentication and their own e-mail. | Test identities you create and control, for your agents and end-to-end tests. |
| How they get in | An e-mailed invite they accept. | You create them; their password is generated or set by a setup link. |
| Workspaces | Can belong to several workspaces, and create their own. | Belong to exactly the workspace that created them. They cannot be invited elsewhere, switch, create or leave workspaces. |
| Counted as people | Yes. | Never. |
Roles are the same for both: a person and a synthetic account with the same role can do the same things. Only a person can be an owner.
Roles
| Role | In the portal | Can |
|---|---|---|
owner | Owner | Everything: people and invites, API keys, workspace settings, flows, the dev panel’s reset, deleting the workspace. A workspace can have several owners, all equal. |
agent_full | Full access | Works disputes and evidence, creates reports, and manages webhooks and playbooks. Cannot manage people, keys or settings. |
disputes_only | Disputes | Sees transactions and works disputes (accept, challenge, evidence, notes). No reports, webhooks or playbooks. |
reports_only | Reports | Sees transactions and disputes, and creates and downloads reports. Cannot act on disputes. |
read_only | View only | Sees transactions, disputes, evidence, reports, webhooks and playbooks. Changes nothing. The default in the invite dialog. |
A role applies only in its workspace: the same person can be an owner of your Development workspace and View only in Production. People who are not owners have no Team page; under Settings > Workspacesthey see each workspace's owners, so they know whom to ask.
Owner-affecting changes need a recent second factor, the same check as creating an API key: inviting someone as an owner, promoting or demoting an owner, and removing one need a code from the last 5 minutes; inviting or promoting someone to Full access, the last 15 minutes. An owner without two-factor authentication adds it under Security first.
Invite a colleague
- On Team > People, choose Invite people. The dialog names the workspace and its environment, so you can see where you are inviting to.
- Enter one to ten addresses and pick a role (View only unless you change it). Each address gets its own result: Sent, Already a member, Already invited (resent), Synthetic account address, or Try again in N seconds.
- The colleague gets a mail from
notifications@dispute.marketswith an Accept invite button. The link works once and expires after 7 days, or 72 hours for an owner invite. You never see the link.
Pending invites are listed under the people, with their status: Invited (expires in N days), Invite expired or Invite bounced. Resend invite mails a new link and the old one stops working; Revoke invite cancels it.
From a script, with a signed-in owner's session token (see Scripts):
curl -s https://api.dispute.markets/v1/team/invites \
-H "Authorization: Bearer $DM_SESSION" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"email": "dana@acme.com", "role": "read_only"}'
curl -s https://api.dispute.markets/v1/team/invites \
-H "Authorization: Bearer $DM_SESSION"POST /v1/team/invites answers 201 with the invite, never its link, whether or not the address already has an account. An address that already has a pending invite answers invite_pending with its id: resend that one with POST /v1/team/invites/{id}/resend. Inviting the sign-in address of one of this workspace's own synthetic accounts is synthetic_address.
Accepting an invite
The link opens a page that says who invited you, to which workspace and environment, with which role, and shows the invited address masked (d•••@acme.com). Opening it uses nothing up, so a mail scanner that follows links is harmless.
| You are | What happens |
|---|---|
| Signed out | Sign in, or Create an account. An account made from an invite gets no sandbox workspace of its own; the code that verifies its address also accepts the invite. |
| Signed in, the invited address is verified on your account | Join. You land on the workspace's dashboard as your new role. |
| Signed in with another address | Add this address to your account: type it, enter the code we mail to it, and join. Or sign out and use another account, or ask an owner to invite the address you already use. |
| Already a member | Open the workspace. |
| The link expired, was used or was revoked | The page says which. Ask someone at the workspace for a new invite; only owners can send one. |
| Signed in as a synthetic account | Synthetic accounts cannot join other workspaces. |
The invited address must be a verified address of the account that accepts, and it must match exactly: plus tags and dots count (dana+qa@acme.com is not dana@acme.com). A forwarded invite is therefore useless to anyone else.
Lost the mail? Pending invites in the app
Invites to any verified address of your account also show in the workspace menu as Pending invites (N) and on the workspace chooser, where you accept them in place. From a script:
curl -s https://api.dispute.markets/v1/me/invites \
-H "Authorization: Bearer $DM_SESSION"
curl -s -X POST https://api.dispute.markets/v1/me/invites/wi_…/accept \
-H "Authorization: Bearer $DM_SESSION"Accepting answers with the workspace, your role and a session already switched into it.
Several owners, and the last owner
Promote anyone to Owner with Change role…. Owners are equal: any owner can change any role, including another owner's. Every workspace needs an owner, so the last owner cannot leave, be removed or be demoted. Their row says “Every workspace needs an owner. Make someone else an owner first.”, and the API answers last_owner. When you are the only owner and the only person, delete the workspace instead (see Workspaces).
curl -s https://api.dispute.markets/v1/team/members \
-H "Authorization: Bearer $DM_SESSION"
curl -s -X PATCH https://api.dispute.markets/v1/team/members/wm_… \
-H "Authorization: Bearer $DM_SESSION" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"role": "disputes_only"}'Removing someone
Remove from workspace…takes effect on the person's very next request:
- Their sessions in this workspace end: the next call answers
account_revokedand the portal takes them to their other workspaces. They are not signed out of the other workspaces they belong to. - The API keys they created or last rotated stop working in this workspace on their next call (
invalid_api_key), and are revoked for good shortly after. The dialog counts them first and offers to rotate a key you want to keep: a rotated key belongs to whoever rotated it. - Their running and queued background tasks in this workspace are cancelled.
- Invites they sent that are still pending are cancelled if they were an owner.
- Their past actions stay in Activity, shown as their e-mail with “(removed)”.
To come back, they need a new invite. A person can also leave on their own, from Settings > Workspaces.
curl -s https://api.dispute.markets/v1/team/members/wm_…/removal-preview \
-H "Authorization: Bearer $DM_SESSION"
curl -s -X DELETE https://api.dispute.markets/v1/team/members/wm_… \
-H "Authorization: Bearer $DM_SESSION" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"synthetic_accounts": [], "created_items": []}'What a person leaves behind
Three things a person set up could outlive their access, so the remove dialog (and demoting an owner, and leaving) asks about each:
| What | Your choice | Why |
|---|---|---|
| Synthetic accounts whose mail goes to their mailbox | Move to me (the account gets an address on your mailbox, and its credentials are reset) or Archive. One choice per account is required (disposition_required). | Password resets and setup links go to that mailbox, so whoever reads it could otherwise sign in as the account. |
| Synthetic accounts whose password they saw or set (they created it with a generated password, rotated it, or completed its setup link) | Reset its credentials (preselected) or Archive. | A password they know keeps working after they go. Reset gives the account a password nobody is shown and ends its sessions; rotate its credentials (or send a new setup link) to use it again. |
| Webhooks, webhook sinks and playbooks they created in the portal | Disable (preselected) or Keep as mine. | A departing colleague’s webhook could keep sending your dispute data to their server. |
| People they invited | Listed for your review; nothing happens to them. | So you can spot an account they added for themselves. |
Someone leaving cannot move accounts onto another owner's mailbox: they archive them, or an owner uses Move mail to me on the Synthetic accounts tab first. Until then leaving answers synthetic_mail_owner. Everything a leaver created is disabled, and the credentials of every other synthetic account whose password they know are reset unless they archive it.
Notices
The owners get a short security mail whenever someone joins (any role), an owner is added or removed, or a role changes to or from Owner or Full access. It goes to the owners as they were before the change, so a change can never be hidden from the person it affects. A removed person is told they were removed. Every member is told when a workspace is deleted. Every invite, acceptance, role change and removal is also in Activity; the People chip shows just those.
Limits
| Limit | Value |
|---|---|
| People per workspace | 50 (synthetic accounts do not count) |
| Pending invites per workspace | 25 (invite_pending_limit) |
| Invites per workspace | 20 an hour, 60 a day |
| Invites per inviter, across all their workspaces | 30 a day; 5 a day for accounts younger than 7 days or without two-factor authentication |
| Invites to one address | 3 a day from one workspace, and 3 a day from one inviter |
| Sends of one invite | One a minute, 5 a day |
Over a limit the answer is invite_rate_limited with Retry-After. An address our mail provider cannot deliver to answers invite_undeliverable and nothing is sent.
Inviting is paused
When a recipient marks an invite as spam, inviting is paused for the inviter in alltheir workspaces for 24 hours. The People tab says “Inviting is paused until <time> because a recipient marked an invite as spam.” and the API answers invite_paused with details.retry_after_s. Other owners can still invite.
Scripts
People, invites and workspaces are managed by a person, so these routes take a signed-in session and never an API key (a key gets api_key_not_allowed). In a script, sign in with POST /v1/auth/signin (identifier is your username or e-mail), finish with POST /v1/auth/mfa/verify when the answer says mfa_required, and send the access_token as $DM_SESSION. Every route, field and error is in the API reference.