Guide

Team: people and synthetic accounts

Invite your colleagues into a workspace. Each person signs in with their own dispute.markets account, and you choose what they can do there. The test identities you already create, synthetic accounts, work exactly as before, on a tab of their own.

People and synthetic accounts

Team in the sidebar (owners only) has two tabs:

PeopleSynthetic accounts
WhoYour 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 inAn e-mailed invite they accept.You create them; their password is generated or set by a setup link.
WorkspacesCan 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 peopleYes.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

RoleIn the portalCan
ownerOwnerEverything: 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_fullFull accessWorks disputes and evidence, creates reports, and manages webhooks and playbooks. Cannot manage people, keys or settings.
disputes_onlyDisputesSees transactions and works disputes (accept, challenge, evidence, notes). No reports, webhooks or playbooks.
reports_onlyReportsSees transactions and disputes, and creates and downloads reports. Cannot act on disputes.
read_onlyView onlySees 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

  1. On Team > People, choose Invite people. The dialog names the workspace and its environment, so you can see where you are inviting to.
  2. 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.
  3. The colleague gets a mail from notifications@dispute.markets with 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):

Invite, then list invites
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 areWhat happens
Signed outSign 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 accountJoin. You land on the workspace's dashboard as your new role.
Signed in with another addressAdd 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 memberOpen the workspace.
The link expired, was used or was revokedThe page says which. Ask someone at the workspace for a new invite; only owners can send one.
Signed in as a synthetic accountSynthetic 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:

Invites waiting for you, and accept one
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).

List people, change a role
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_revoked and 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.

See what removal affects, then remove
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:

WhatYour choiceWhy
Synthetic accounts whose mail goes to their mailboxMove 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 portalDisable (preselected) or Keep as mine.A departing colleague’s webhook could keep sending your dispute data to their server.
People they invitedListed 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

LimitValue
People per workspace50 (synthetic accounts do not count)
Pending invites per workspace25 (invite_pending_limit)
Invites per workspace20 an hour, 60 a day
Invites per inviter, across all their workspaces30 a day; 5 a day for accounts younger than 7 days or without two-factor authentication
Invites to one address3 a day from one workspace, and 3 a day from one inviter
Sends of one inviteOne 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.