Manage members

Invite people to a merchant account, change their roles, and remove access.

Add members to a merchant account so each person can sign in with their own user account. Assign roles to control what they can do. You can also create managed users when the merchant needs to manage the user’s login.

See Run the examples for shared setup.

Required access

The user making each request needs the corresponding permission. For OAuth requests, the token must also have either of the listed scopes.

Action User permission OAuth scopes
List members merchant_read user.subaccounts or members.read
View a member members_view user.subaccounts or members.read
Invite or create a member members_create user.subaccounts or members.write
Change a member’s roles members_update user.subaccounts or members.write
Remove a member members_delete user.subaccounts or members.write

Invite a member

  1. Choose a system role for the new member.
  2. Call Create a member with the person’s email address and the roles to assign.

The following examples invite teammate@example.com with the Employee role. Replace the email address before sending a real invitation.

Invite a member
curl --request POST \
  "https://api.sumup.com/v0.1/merchants/${SUMUP_MERCHANT_CODE}/members" \
  --header "Authorization: Bearer ${SUMUP_ACCESS_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{
    "email": "teammate@example.com",
    "roles": ["role_employee"]
  }'
import SumUp from "@sumup/sdk";

const client = new SumUp({ apiKey: process.env.SUMUP_ACCESS_TOKEN! });
const member = await client.members.create(process.env.SUMUP_MERCHANT_CODE!, {
  email: "teammate@example.com",
  roles: ["role_employee"],
});
console.log(member.id);
import os

from sumup import Sumup

client = Sumup(api_key=os.environ["SUMUP_ACCESS_TOKEN"])
member = client.members.create(
    os.environ["SUMUP_MERCHANT_CODE"],
    email="teammate@example.com",
    roles=["role_employee"],
)
print(member.id)
<?php

require __DIR__ . '/vendor/autoload.php';

$client = new \SumUp\SumUp(getenv('SUMUP_ACCESS_TOKEN'));
$member = $client->members()->create(getenv('SUMUP_MERCHANT_CODE'), [
    'email' => 'teammate@example.com',
    'roles' => ['role_employee'],
]);
echo $member->id, PHP_EOL;
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/sumup/sumup-go"
	sumupclient "github.com/sumup/sumup-go/client"
)

func main() {
	client := sumup.NewClient(sumupclient.WithAPIKey(os.Getenv("SUMUP_ACCESS_TOKEN")))
	member, err := client.Members.Create(context.Background(), os.Getenv("SUMUP_MERCHANT_CODE"), sumup.MembersCreateParams{
		Email: "teammate@example.com",
		Roles: []string{"role_employee"},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(member.ID)
}
import com.sumup.sdk.SumUpClient;
import com.sumup.sdk.models.CreateMerchantMemberRequest;
import java.util.List;

public class Main {
  public static void main(String[] args) throws Exception {
    var client = new SumUpClient(System.getenv("SUMUP_ACCESS_TOKEN"));
    var member = client.members().create(
        System.getenv("SUMUP_MERCHANT_CODE"),
        CreateMerchantMemberRequest.builder()
            .email("teammate@example.com")
            .roles(List.of("role_employee"))
            .build());
    System.out.println(member.id());
  }
}
using System;
using SumUp;

using var client = new SumUpClient(); // Reads SUMUP_ACCESS_TOKEN.
var response = await client.Members.CreateAsync(
    Environment.GetEnvironmentVariable("SUMUP_MERCHANT_CODE")!,
    new MembersCreateRequest
    {
        Email = "teammate@example.com",
        Roles = new[] { "role_employee" },
    });
Console.WriteLine(response.Data?.Id);
use sumup::{resources::members::CreateRequest, Authorization, Client};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::default().with_authorization(Authorization::api_key(
        std::env::var("SUMUP_ACCESS_TOKEN")?,
    ));
    let member = client
        .members()
        .create(
            std::env::var("SUMUP_MERCHANT_CODE")?,
            CreateRequest {
                email: "teammate@example.com".into(),
                roles: vec!["role_employee".into()],
                is_managed_user: None,
                password: None,
                nickname: None,
                metadata: None,
                attributes: None,
            },
        )
        .await?;
    println!("{}", member.id);
    Ok(())
}

The API returns HTTP 201 and a member object. Save its id if you need to update or remove this member later. The person receives an email invitation and must accept it before accessing the account.

Call Get a member or List members to check their status. A pending invitation has status pending; after acceptance, the member has status accepted.

If an invitation expires, the status is expired. To replace it, remove its member entry with Delete a member, then invite the person again. Creating another invitation while an entry for that email already exists is rejected.

If the API returns HTTP 429, wait until the time indicated by Retry-After before retrying.

Review members and change roles

Use List members to review who has access to the account. You can filter the results by email prefix, role, or status. The response is paginated: use limit and offset to retrieve additional pages, with at most 25 members per page.

The following request retrieves the first page of accepted members:

List accepted members
curl --get \
  "https://api.sumup.com/v0.1/merchants/${SUMUP_MERCHANT_CODE}/members" \
  --header "Authorization: Bearer ${SUMUP_ACCESS_TOKEN}" \
  --data-urlencode "status=accepted" \
  --data-urlencode "limit=25" \
  --data-urlencode "offset=0"

The API returns HTTP 200 with an items array and total_count. Increase offset by the number of items returned to retrieve the next page. Use a member’s id to update their roles or remove their access.

Assign a role to a member

The user making the request needs members_update. For OAuth requests, the token also needs user.subaccounts or members.write.

Set SUMUP_ROLE_ID to the system role to assign, such as role_manager. Use List members to find the member and check their current roles. Set SUMUP_MEMBER_ID to their member ID.

The roles array replaces the member’s current roles. Include every role the member should keep. These examples assign only the selected role, removing any other roles from the member:

Assign a role to a member
curl --request PUT \
  "https://api.sumup.com/v0.1/merchants/${SUMUP_MERCHANT_CODE}/members/${SUMUP_MEMBER_ID}" \
  --header "Authorization: Bearer ${SUMUP_ACCESS_TOKEN}" \
  --header "Content-Type: application/json" \
  --data "{\"roles\":[\"${SUMUP_ROLE_ID}\"]}"
import SumUp from "@sumup/sdk";

const client = new SumUp({ apiKey: process.env.SUMUP_ACCESS_TOKEN! });
const member = await client.members.update(
  process.env.SUMUP_MERCHANT_CODE!,
  process.env.SUMUP_MEMBER_ID!,
  { roles: [process.env.SUMUP_ROLE_ID!] },
);
console.log(member);
import os

from sumup import Sumup

client = Sumup(api_key=os.environ["SUMUP_ACCESS_TOKEN"])
member = client.members.update(
    os.environ["SUMUP_MERCHANT_CODE"],
    os.environ["SUMUP_MEMBER_ID"],
    roles=[os.environ["SUMUP_ROLE_ID"]],
)
print(member)
<?php

require __DIR__ . '/vendor/autoload.php';

$client = new \SumUp\SumUp(getenv('SUMUP_ACCESS_TOKEN'));
$member = $client->members()->update(
    getenv('SUMUP_MERCHANT_CODE'),
    getenv('SUMUP_MEMBER_ID'),
    ['roles' => [getenv('SUMUP_ROLE_ID')]],
);
var_dump($member);
package main

import (
    "context"
    "fmt"
    "log"
    "os"

    "github.com/sumup/sumup-go"
    sumupclient "github.com/sumup/sumup-go/client"
)

func main() {
    client := sumup.NewClient(sumupclient.WithAPIKey(os.Getenv("SUMUP_ACCESS_TOKEN")))
    member, err := client.Members.Update(
        context.Background(),
        os.Getenv("SUMUP_MERCHANT_CODE"),
        os.Getenv("SUMUP_MEMBER_ID"),
        sumup.MembersUpdateParams{Roles: []string{os.Getenv("SUMUP_ROLE_ID")}},
    )
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%+v\n", member)
}
import com.sumup.sdk.SumUpClient;
import com.sumup.sdk.models.UpdateMerchantMemberRequest;
import java.util.List;

public class Main {
  public static void main(String[] args) throws Exception {
    var client = new SumUpClient(System.getenv("SUMUP_ACCESS_TOKEN"));
    var member = client.members().update(
        System.getenv("SUMUP_MEMBER_ID"),
        System.getenv("SUMUP_MERCHANT_CODE"),
        UpdateMerchantMemberRequest.builder()
            .roles(List.of(System.getenv("SUMUP_ROLE_ID")))
            .build());
    System.out.println(member);
  }
}
using System;
using SumUp;

using var client = new SumUpClient(); // Reads SUMUP_ACCESS_TOKEN.
var response = await client.Members.UpdateAsync(
    Environment.GetEnvironmentVariable("SUMUP_MERCHANT_CODE")!,
    Environment.GetEnvironmentVariable("SUMUP_MEMBER_ID")!,
    new MembersUpdateRequest
    {
        Roles = new[] { Environment.GetEnvironmentVariable("SUMUP_ROLE_ID")! },
    });
Console.WriteLine(response.Data);
use sumup::{resources::members::UpdateRequest, Authorization, Client};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::default().with_authorization(Authorization::api_key(
        std::env::var("SUMUP_ACCESS_TOKEN")?,
    ));
    let member = client
        .members()
        .update(
            std::env::var("SUMUP_MERCHANT_CODE")?,
            std::env::var("SUMUP_MEMBER_ID")?,
            UpdateRequest {
                roles: Some(vec![std::env::var("SUMUP_ROLE_ID")?]),
                ..Default::default()
            },
        )
        .await?;
    println!("{member:#?}");
    Ok(())
}

The API returns HTTP 200 and the updated member. You can also assign roles when inviting a new member.

Verify the member’s access

Call Get a member and check their saved roles. Test an action the role allows and one it should deny using the member’s credentials and the required OAuth scopes. A successful request made as the account owner does not verify the member’s access.

Managed users

An invited member signs in with their own user account. A managed user’s login is managed by the merchant instead, and no invitation is sent. Managed users cannot reset their own password; the merchant must change it with Update a member.

To create a managed user, call Create a member with is_managed_user: true, an email address, a password, and the roles to assign. You can also provide a nickname for display. The password must contain at least eight characters.

Export SUMUP_MANAGED_USER_PASSWORD with the password for the new managed user. The following request creates cashier@example.com with the Employee role. Replace the email address before sending the request.

Create a managed user
curl --request POST \
  "https://api.sumup.com/v0.1/merchants/${SUMUP_MERCHANT_CODE}/members" \
  --header "Authorization: Bearer ${SUMUP_ACCESS_TOKEN}" \
  --json "$(jq -n '{
    email: "cashier@example.com",
    is_managed_user: true,
    password: env.SUMUP_MANAGED_USER_PASSWORD,
    nickname: "Cashier",
    roles: ["role_employee"]
  }')"

This example requires jq(Opens in a new tab) to encode the password safely as JSON. The API returns HTTP 201 and the new member. No invitation needs to be accepted before the managed user can sign in.

Use Update a member to change a managed user’s user.nickname or user.password. These fields are not available for invited users. Setting a new password also enables the managed user’s account.

Remove access

Removing a managed user from their last merchant account also deletes their login and ends their sessions. Check which type of user you are removing before proceeding.

  1. Use Get a member to confirm you have the correct person and account.
  2. Call Delete a member with the merchant code and the member’s id.
  3. Confirm that the member no longer appears in List members.

The delete request returns HTTP 200 with an empty body. For an invited user, removal affects access to this merchant account; it does not remove their access to other merchant accounts.

Some members, including the account owner and Admin members, are protected from removal through this endpoint. The Members API also does not support removing service accounts.

Type to search…