Managing User Memberships

Medallion user authorization is controlled by memberships within your organization. We support several APIs to allow you to manage your memberships programmatically. The member lifecycle most commonly follows these steps:

  1. Create a new member
  2. [Optional] Send the member an invitation to sign up for Medallion
  3. Change a member email
  4. Deactivate a member
  5. Reactivate a deactivated member

Creating a Membership

In order for a user to view your organization in Medallion they must have a membership. You can create a membership using the Members endpoint. To use the endpoint you will need the user's email and the role they should be granted in Medallion.

📘

Save your IDs!

Make sure to save the member ID returned when you create a Membership! You'll need this to send invitations and update the membership later.

If at any point you lost track of your Member IDs, you can use the GET Members endpoint with a user__email to find them again, e.g. with requests.get(membership_url, params={"user__email": "[email protected]"}, headers=headers).

import requests

api_key = "<YOUR_API_KEY>"
organization_id = "<YOUR_ORG_ID>"
base_url = "https://api.medallion.co"

headers = {"x-api-key": api_key, "accept": "application/json"}

membership_url = f"{base_url}/p/api/v1/organizations/members/"

# Placeholder data.  In practice, this will probably be loaded from a spreadsheet or other source.
member_data = [
    {
        "email": "[email protected]",
      	"role": "admin",
        "last_name": "Doe",
    },
    {
        "email": "[email protected]",
      	"role": "auditor",
    },
  	{
        "email": "[email protected]",
      	"role": "provider",
        "profession": "MD",
        "first_name": "Jane",
        "last_name": "Doe",
    },
    {"email": "[email protected]", "role": "super_provider", "profession": "DO", "first_name": "Cher"},
]

# Iterate over members, create a membership for each, and store the member ID
for member in member_data:
  	member_json = {
        "role": member["role"],
        "user": {"email": member["email"]},
    }
    if member.get("profession"):
        member_json["provider"] = {"profession": member["profession"]},
    response = requests.post(
        membership_url,
        json=member_json,
        headers=headers,
    )
    response.raise_for_status()
    response_json = response.json()
    
    # We recommend always storing member and provider ids for later use
    if response_json.get("provider"):
    	member["provider_id"] = response_json["provider"]["id"]
    member["membership_id"] = response_json["id"]

👍

Medallion member roles

  • admin - This is generally a staff member at your organization who will be helping to enter information about your organization or providers, requesting work from Medallion, and following up on the progress of work within Medallion.
  • auditor - This is generally a staff member who needs to track work within Medallion or review provider data but should not update or enter information within Medallion.
  • provider - This is a medical professional within your organization who needs to have a profile within Medallion but should not be able to request work from Medallion or view organization data outside of their profile.
  • super_provider - This is a provider who will need to have a profile within Medallion but is also an admin who needs to enter information about your organization or request work from Medallion.
  • medical_staff_professional - This is an uncommon role for an admin who needs to complete specific work within Medallion. Please work with your CSM if you think you need this role.

Sending an Invitation

Memberships manage authorization to Medallion. Invitations manage authentication or the ability to log in to Medallion. You will need to create an invitation for members that should log in to Medallion via POST Invite. Invitations will be automatically emailed to the user and include a sign up link to Medallion. If a user should not log in, you do not need to complete this step. Invitations are usually needed for admin and auditor and super_provider users but may not be needed for provider users if their data will be entered and managed by other users.

📘

Save your IDs!

Make sure to save the invite ID returned when you create an Invite! You'll need this to update the invitation later.

If at any point you lost track of your Invite IDs, you can use the GET Invites to access all invites in your organization, e.g. with requests.get(invite_url, headers=headers). You can then filter the response by member ID to find the invite ID for a particular member.

invites_url = f"{base_url}/p/api/v1/organizations/{organization_id}/invites/"

# Iterate over the member data again and send an invitation to each member
# Could be done in the same loop as above, but split out here for readability
for member in member_data:
    response = requests.post(
        invites_url, json={"membership_id": member["membership_id"]}, headers=headers
    )
    response.raise_for_status()
    response_json = response.json()

    # We recommend always storing the invite ids for later use
    member["invite_id"] = response_json["id"]

Resending an Invitation

Sometimes a user may miss their invitation email and need it to be resent. You can resend an invitation email via POST Resend Invite.

# Choose an example member for the rest of the example code
member = member_data[0]

resend_invite_url = f"{base_url}/p/api/v1/organizations/invites/{member["invite_id"]}/resend/"

# Resend the invite email
response = requests.post(
    resend_invite_url, headers=headers
)
response.raise_for_status()

Revoking an Invitation

If you invite a user who should not be able to log in to the platform you can revoke an invite via POST Revoke Invite.

revoke_invite_url = f"{base_url}/p/api/v1/organizations/invites/{member["invite_id"]}/revoke/"

# Revoke the invite, the emailed sign up code will be automatically invalidated
response = requests.post(
    revoke_invite_url, headers=headers
)
response.raise_for_status()

Changing a Member's Email

If a user's email changes you can update it via POST Membership Email Update. This will change the user's login email and the email that Medallion communications are sent to.

email_change_url = f"{base_url}/p/api/v1/organizations/members/{member["membership_id"]}/change-email/"

# Update the user's email, this will update their login email and the email where they receive 
# Medallion notifications
response = requests.post(
    email_change_url, json={"new_email":"[email protected]"}, headers=headers
)
response.raise_for_status()

Updating a Member's Activity Status

As employees and providers join and leave your organization, you may need to add and remove access for your members. Medallion allows you to manage this by updating the is_active attribute of a membership.

member_detail_url = f"{base_url}/p/api/v1/organizations/members/{member["membership_id"]}/"

# De-activate the member, the member will no longer be able to view your organization data 
# in Medallion
response = requests.patch(
    member_detail_url,
    json={"is_active":False},
    headers=headers,
)
response.raise_for_status()

# Re-activate the member, the member will be able to view your organization data in Medallion
response = requests.patch(
    member_detail_url,
    json={"is_active":True},
    headers=headers,
)
response.raise_for_status()

Code Roundup

import requests

api_key = "<YOUR_API_KEY>"
organization_id = "<YOUR_ORG_ID>"
base_url = "https://api.medallion.co"

headers = {"x-api-key": api_key, "accept": "application/json"}

membership_url = f"{base_url}/p/api/v1/organizations/members/"

# Placeholder data.  In practice, this will probably be loaded from a spreadsheet or other source.
member_data = [
    {
        "email": "[email protected]",
      	"role": "admin",
        "last_name": "Doe",
    },
    {
        "email": "[email protected]",
      	"role": "auditor",
    },
  	{
        "email": "[email protected]",
      	"role": "provider",
        "profession": "MD",
        "first_name": "Jane",
        "last_name": "Doe",
    },
    {"email": "[email protected]", "role": "super_provider", "profession": "DO", "first_name": "Cher"},
]

# Iterate over members, create a membership for each, and store the member ID
for member in member_data:
  	member_json = {
        "role": member["role"],
        "user": {"email": member["email"]},
    }
    if member.get("profession"):
        member_json["provider"] = {"profession": member["profession"]},
    response = requests.post(
        membership_url,
        json=member_json,
        headers=headers,
    )
    response.raise_for_status()
    response_json = response.json()
    
    # We recommend always storing member and provider ids for later use
    if response_json.get("provider"):
    	member["provider_id"] = response_json["provider"]["id"]
    member["membership_id"] = response_json["id"]
    
invites_url = f"{base_url}/p/api/v1/organizations/{organization_id}/invites/"

# Iterate over the member data again and send an invitation to each member
# Could be done in the same loop as above, but split out here for readability
for member in member_data:
    response = requests.post(
        invites_url, json={"membership_id": member["membership_id"]}, headers=headers
    )
    response.raise_for_status()
    response_json = response.json()

    # We recommend always storing the invite ids for later use
    member["invite_id"] = response_json["id"]

# Choose an example member for the rest of the example code
member = member_data[0]

resend_invite_url = f"{base_url}/p/api/v1/organizations/invites/{member["invite_id"]}/resend/"

# Resend the invite email
response = requests.post(
    resend_invite_url, headers=headers
)
response.raise_for_status()

revoke_invite_url = f"{base_url}/p/api/v1/organizations/invites/{member["invite_id"]}/revoke/"

# Revoke the invite, the emailed sign up code will be automatically invalidated
response = requests.post(
    revoke_invite_url, headers=headers
)
response.raise_for_status()

email_change_url = f"{base_url}/p/api/v1/organizations/members/{member["membership_id"]}/change-email/"

# Update the user's email, this will update their login email and the email where they receive 
# Medallion notifications
response = requests.post(
    email_change_url, json={"new_email":"[email protected]"}, headers=headers
)
response.raise_for_status()

member_detail_url = f"{base_url}/p/api/v1/organizations/members/{member["membership_id"]}/"

# De-activate the member, the member will no longer be able to view your organization data 
# in Medallion
response = requests.patch(
    member_detail_url,
    json={"is_active":False},
    headers=headers,
)
response.raise_for_status()

# Re-activate the member, the member will be able to view your organization data in Medallion
response = requests.patch(
    member_detail_url,
    json={"is_active":True},
    headers=headers,
)
response.raise_for_status()