Skip to content

From Sign-up to ATP

Create an account, invite people, and produce a client, project, SOW and acceptance test plan from a terminal or an MCP client

This page goes from nothing to an acceptance test plan (ATP). Each step shows both routes:

  • Terminal uses curl and jq. It works anywhere an agent can run shell commands, including Pi.
  • MCP is what to ask an assistant connected through MCP, with the tool it calls.

Terminal commands build on each other, so run them in one shell session or keep the IDs they print.

  1. Create your account

    Set the addresses and your details. Use an email address you control. Password sign-in needs at least 8 characters.

    export TANDA_APP=https://www.testandaccept.com
    export TANDA_API=https://api.testandaccept.com/api/rest
    export TANDA_JAR="$(mktemp)"
    export TANDA_NAME="Ada Lovelace"
    export TANDA_EMAIL="ada@example.com"
    export TANDA_PASSWORD="$(openssl rand -base64 24)"

    Save the generated password in your password manager, then sign up. The session is kept in the cookie file:

    curl -sS --fail-with-body -b "$TANDA_JAR" -c "$TANDA_JAR" "$TANDA_APP/api/auth/sign-up/email" \
      -H "Origin: $TANDA_APP" -H 'Content-Type: application/json' \
      -d "$(jq -n --arg name "$TANDA_NAME" --arg email "$TANDA_EMAIL" --arg password "$TANDA_PASSWORD" \
        '{name: $name, email: $email, password: $password}')" | jq '.user | {id, email}'

    Already have an account? Send the same request to /api/auth/sign-in/email, without name. If you sign in with Google, GitHub or Microsoft, skip to the next step and create your token on the Developer page.

    Sign-up and sign-in allow only a few attempts every few seconds. If you get a 429, wait 10 seconds and try again.

    Add the server to your client. The first time it connects, your client opens the Tanda sign-in page in your browser. Choose to sign up, or sign in if you already have an account, then approve access.

    An account can’t be created over MCP, because connecting needs an account first.

  2. Create an organization

    An organization holds your clients and projects, and your team.

    Create it, make it your active organization, and set up its file storage:

    export TANDA_ORG_NAME="Analytical Engines"
    export TANDA_ORG_SLUG="analytical-engines-$(openssl rand -hex 3)"
    
    export TANDA_ORG_ID="$(curl -sS --fail-with-body -b "$TANDA_JAR" -c "$TANDA_JAR" \
      "$TANDA_APP/api/auth/organization/create" \
      -H "Origin: $TANDA_APP" -H 'Content-Type: application/json' \
      -d "$(jq -n --arg name "$TANDA_ORG_NAME" --arg slug "$TANDA_ORG_SLUG" '{name: $name, slug: $slug}')" \
      | jq -r .id)"
    
    curl -sS --fail-with-body -o /dev/null -b "$TANDA_JAR" -c "$TANDA_JAR" \
      "$TANDA_APP/api/auth/organization/set-active" \
      -H "Origin: $TANDA_APP" -H 'Content-Type: application/json' \
      -d "$(jq -n --arg id "$TANDA_ORG_ID" '{organizationId: $id}')"
    
    curl -sS -o /dev/null -w 'File storage: %{http_code}\n' -b "$TANDA_JAR" "$TANDA_APP/api/organizations/provision" \
      -H "Origin: $TANDA_APP" -H 'Content-Type: application/json' \
      -d "$(jq -n --arg id "$TANDA_ORG_ID" --arg name "$TANDA_ORG_NAME" \
        '{organizationId: $id, organizationName: $name}')"
    
    echo "Organization: $TANDA_ORG_ID"

    The last request sets up file storage and should print 200. If it fails, you can still carry on with the rest of this page.

    Open testandaccept.com/organization-setup in your browser to create one. Then ask:

    Which Tanda organizations can I work in?

    The assistant calls list_organizations. If you belong to more than one, tell it which to use and it calls set_default_organization.

  3. Create a token

    Create an API token. It’s only shown once, and every request after this uses it:

    export TANDA_TOKEN="$(curl -sS --fail-with-body -b "$TANDA_JAR" "$TANDA_APP/api/api-token" \
      -H "Origin: $TANDA_APP" -H 'Content-Type: application/json' \
      -d '{"name": "agent"}' | jq -r .token)"

    Save it in your secrets manager. Check that it works:

    curl -sS --fail-with-body "$TANDA_API/projects" -H "Authorization: Bearer $TANDA_TOKEN" | jq .total

    A new organization has no projects yet, so this prints 0.

    Nothing to do: your client signed in when it connected.

  4. Create a client and a project

    export TANDA_CLIENT_ID="$(curl -sS --fail-with-body "$TANDA_API/clients" \
      -H "Authorization: Bearer $TANDA_TOKEN" -H 'Content-Type: application/json' \
      -d '{"name": "Globex", "industry": "Manufacturing"}' | jq -r .id)"
    
    export TANDA_PROJECT_ID="$(curl -sS --fail-with-body "$TANDA_API/projects" \
      -H "Authorization: Bearer $TANDA_TOKEN" -H 'Content-Type: application/json' \
      -d "$(jq -n --arg client "$TANDA_CLIENT_ID" '{name: "Customer portal", clientId: $client}')" \
      | jq -r .id)"
    
    echo "Client: $TANDA_CLIENT_ID  Project: $TANDA_PROJECT_ID"

    Create a client called Globex in manufacturing, and a project for them called Customer portal.

    The assistant calls create_client and then create_project.

  5. Invite people

    There are two kinds of invitation. A project invitation gives someone access to one project. An organization invitation makes them a member of your organization.

    To a project. Access levels are owner, editor, approver, viewer and follower. Tanda emails the person. If an account has already verified that address, they’re added straight away and notified:

    curl -sS --fail-with-body "$TANDA_API/projects/$TANDA_PROJECT_ID/invitations" \
      -H "Authorization: Bearer $TANDA_TOKEN" -H 'Content-Type: application/json' \
      -d '{"email": "grace@example.com", "accessLevel": "editor", "message": "Please review the plan"}'

    To the organization. Roles are admin and member, and you must be an admin. Tanda does not email this one. Send the person the acceptUrl from the response:

    curl -sS --fail-with-body "$TANDA_API/organization/invitations" \
      -H "Authorization: Bearer $TANDA_TOKEN" -H 'Content-Type: application/json' \
      -d '{"email": "grace@example.com", "role": "member"}' | jq -r .acceptUrl

    The link lasts 7 days and only works for an account with the invited email address.

    Invite grace@example.com to Customer portal as an editor.

    The assistant calls invite_project_member, which sends no email. It gives you an acceptUrl, and you send that to the person. The link lasts 7 days and only works for an account with the invited email address.

    Organization invitations aren’t available over MCP. Use the Terminal route, or invite people from your organization settings in the app.

  6. Write the statement of work

    A SOW holds task items. Each item has acceptance criteria, and each criterion has the tests that prove it. Add one of each here, and repeat for the rest of your work.

    export TANDA_SOW_ID="$(curl -sS --fail-with-body "$TANDA_API/projects/$TANDA_PROJECT_ID/sows" \
      -H "Authorization: Bearer $TANDA_TOKEN" -H 'Content-Type: application/json' \
      -d '{"title": "Phase 1", "description": "Customers sign in and see their orders."}' | jq -r .id)"
    
    export TANDA_ITEM_ID="$(curl -sS --fail-with-body "$TANDA_API/task-items" \
      -H "Authorization: Bearer $TANDA_TOKEN" -H 'Content-Type: application/json' \
      -d "$(jq -n --arg sow "$TANDA_SOW_ID" '{sowId: $sow, title: "Sign-in page"}')" | jq -r .id)"
    
    export TANDA_CRITERION_ID="$(curl -sS --fail-with-body "$TANDA_API/task-items/$TANDA_ITEM_ID/criteria" \
      -H "Authorization: Bearer $TANDA_TOKEN" -H 'Content-Type: application/json' \
      -d '{"title": "Customers can sign in", "acceptanceCriteria": "Valid credentials open the orders page."}' \
      | jq -r .id)"

    Add a test with its procedure:

    curl -sS --fail-with-body "$TANDA_API/criteria/$TANDA_CRITERION_ID/tests" \
      -H "Authorization: Bearer $TANDA_TOKEN" -H 'Content-Type: application/json' \
      -d '{
        "title": "Sign in with valid credentials",
        "testType": "manual",
        "priority": "high",
        "testFormat": "procedural",
        "sections": [{
          "title": "Execution",
          "functions": [{
            "title": "Sign in",
            "prerequisites": "An active customer account exists",
            "steps": [
              {"step": 1, "action": "Open /signin", "expected": "The sign-in form shows"},
              {"step": 2, "action": "Submit valid credentials", "expected": "The orders page opens"}
            ]
          }]
        }]
      }' | jq '{id, title}'

    Create a SOW called Phase 1 in Customer portal from this brief: customers sign in and see their orders. Add task items, acceptance criteria and a detailed test for each criterion.

    The assistant calls create_sow, create_task_item, create_acceptance_criterion and create_test. For a long brief, ask it to use start_sow_generation instead, which drafts the SOW and waits for your approval before saving.

    To find what’s missing, ask it to check coverage. It calls analyze_coverage.

  7. Produce the ATP

    An ATP isn’t a separate record. Tanda generates it from the SOW, so it always matches the current tests. A criterion with no test has nothing to run, so check that every criterion has one.

    As Markdown, or as a PDF to send to your client:

    curl -sS --fail-with-body \
      "$TANDA_APP/api/sow/$TANDA_SOW_ID/export?format=markdown&variant=procedure" \
      -H "Authorization: Bearer $TANDA_TOKEN"
    
    curl -sS --fail-with-body -o atp.pdf \
      "$TANDA_APP/api/sow/$TANDA_SOW_ID/export?format=pdf&variant=procedure" \
      -H "Authorization: Bearer $TANDA_TOKEN"

    Once tests have run, variant=report adds their results.

    Give me the acceptance test plan for Phase 1.

    The assistant calls get_acceptance_test_plan, which returns the plan as Markdown, along with any criteria that have no test. For a PDF, use the Terminal route or export it from the SOW in the app.

Accepting an invitation

Organization invitation. Open the acceptUrl and sign in with the invited address. To do it from a terminal, sign in so you have a session, then use the value after invitation= in the link:

curl -sS --fail-with-body -b "$TANDA_JAR" "$TANDA_APP/api/organization-settings" \
  -H "Origin: $TANDA_APP" -H 'Content-Type: application/json' \
  -d "$(jq -n --arg id "$TANDA_INVITATION" '{action: "accept", invitationId: $id}')"

Then set the organization active, as in step 2, to create a token for it. A token belongs to the organization that was active when it was made.

Project invitation. Open the link, or use the value after token= with an API token from an account with the invited email address. The request must send a JSON body, even an empty one:

curl -sS --fail-with-body "$TANDA_API/project-invitations/$TANDA_INVITE_TOKEN/accept" \
  -H "Authorization: Bearer $TANDA_TOKEN" -H 'Content-Type: application/json' -d '{}'

If something fails

You see What it means What to do
401 from the REST API The token is missing, wrong or revoked Check Authorization: Bearer tnda_..., or create a new token
401 from /mcp tnda_ tokens don’t work on the MCP server Connect through your client’s sign-in
403 Access denied You don’t have access to that record, or it’s in another organization Use a token from the organization that owns it, or ask an owner to invite you
403 Invalid origin A session request has no matching Origin header Send Origin: https://www.testandaccept.com
400 Organization required No organization is active for this session Finish step 2 first
409 on a criterion or test The SOW version is locked after approval Change it through an RFC
415 Missing content-type header A POST has no JSON body Send Content-Type: application/json and -d '{}'
429 Too many attempts Wait 10 seconds and try again
Unsupported protocol version Your MCP client is too old for the server Use the Terminal route (Pi details)

Type to search…

↑↓ navigate↵ selectEsc close