Docs
Dashboard
On this page

    Team

    20 endpoints. Each needs an API key or OAuth token with the scope shown; the key already names its store, so paths start at /v1/store. Generated from the live contract; also in openapi.json.

    Members, pending invites, custom roles and your own access

    GET/v1/store/team

    Or name the store: GET /v1/stores/{storeId}/team

    team:readrole: team:readgetTeam

    Response TeamOverview

    • membersTeamMember[]required
    • invitesTeamInvite[]required
    • rolesCustomRole[]required
    • youStoreAccessrequired

    Example

    curl "https://api.shopfa.st/v1/store/team" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY"
    const res = await fetch('https://api.shopfa.st/v1/store/team', {
      method: 'GET',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
      },
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "GET",
        "https://api.shopfa.st/v1/store/team",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("GET", "https://api.shopfa.st/v1/store/team", nil)
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Invite someone by email. The link works for 7 days.

    POST/v1/store/team/invites

    Or name the store: POST /v1/stores/{storeId}/team/invites

    team:writerole: team:writeinviteMember

    Body

    • emailstringrequired
    • assignmentobjectrequired
      • role"admin" | "staff" | "support" | "finance" | "custom"required
      • customRoleIdrole_… | nullrequired
    • departmentstring | null
    • tagsstring[]
    • expiresInHoursinteger | null

    Response InviteMemberResponse

    • inviteTeamInviterequired
    • acceptUrlstringrequired

    Example

    curl -X POST "https://api.shopfa.st/v1/store/team/invites" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "email": "[email protected]",
      "assignment": {
        "role": "admin",
        "customRoleId": "role_0123456789abcdefghjk"
      },
      "department": null,
      "tags": [],
      "expiresInHours": null
    }'
    const res = await fetch('https://api.shopfa.st/v1/store/team/invites', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        "email": "[email protected]",
        "assignment": {
          "role": "admin",
          "customRoleId": "role_0123456789abcdefghjk"
        },
        "department": null,
        "tags": [],
        "expiresInHours": null
      }),
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "POST",
        "https://api.shopfa.st/v1/store/team/invites",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
        json={
          "email": "[email protected]",
          "assignment": {
            "role": "admin",
            "customRoleId": "role_0123456789abcdefghjk"
          },
          "department": None,
          "tags": [],
          "expiresInHours": None
        },
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("POST", "https://api.shopfa.st/v1/store/team/invites", strings.NewReader(`{
      "email": "[email protected]",
      "assignment": {
        "role": "admin",
        "customRoleId": "role_0123456789abcdefghjk"
      },
      "department": null,
      "tags": [],
      "expiresInHours": null
    }`))
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Send the invite again with a new link and a fresh 7 days

    POST/v1/store/team/invites/{inviteId}/resend

    Or name the store: POST /v1/stores/{storeId}/team/invites/{inviteId}/resend

    team:writerole: team:writeresendInvite

    Parameters

    • inviteIdinv_…pathrequired

    Response ResendInviteResponse

    • inviteTeamInviterequired
    • acceptUrlstringrequired

    Example

    curl -X POST "https://api.shopfa.st/v1/store/team/invites/inv_0123456789abcdefghjk/resend" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY"
    const res = await fetch('https://api.shopfa.st/v1/store/team/invites/inv_0123456789abcdefghjk/resend', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
      },
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "POST",
        "https://api.shopfa.st/v1/store/team/invites/inv_0123456789abcdefghjk/resend",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("POST", "https://api.shopfa.st/v1/store/team/invites/inv_0123456789abcdefghjk/resend", nil)
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Cancel a pending invite

    DELETE/v1/store/team/invites/{inviteId}

    Or name the store: DELETE /v1/stores/{storeId}/team/invites/{inviteId}

    team:writerole: team:writerevokeInvite

    Parameters

    • inviteIdinv_…pathrequired

    Response TeamOverview

    • membersTeamMember[]required
    • invitesTeamInvite[]required
    • rolesCustomRole[]required
    • youStoreAccessrequired

    Example

    curl -X DELETE "https://api.shopfa.st/v1/store/team/invites/inv_0123456789abcdefghjk" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY"
    const res = await fetch('https://api.shopfa.st/v1/store/team/invites/inv_0123456789abcdefghjk', {
      method: 'DELETE',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
      },
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "DELETE",
        "https://api.shopfa.st/v1/store/team/invites/inv_0123456789abcdefghjk",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("DELETE", "https://api.shopfa.st/v1/store/team/invites/inv_0123456789abcdefghjk", nil)
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Change a member's role (the owner's role changes only through a transfer)

    PUT/v1/store/team/members/{userId}/role

    Or name the store: PUT /v1/stores/{storeId}/team/members/{userId}/role

    team:writerole: team:writeupdateMemberRole

    Parameters

    • userIdstringpathrequired

    Body

    • role"admin" | "staff" | "support" | "finance" | "custom"required
    • customRoleIdrole_… | nullrequired

    Response TeamOverview

    • membersTeamMember[]required
    • invitesTeamInvite[]required
    • rolesCustomRole[]required
    • youStoreAccessrequired

    Example

    curl -X PUT "https://api.shopfa.st/v1/store/team/members/string/role" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "role": "admin",
      "customRoleId": "role_0123456789abcdefghjk"
    }'
    const res = await fetch('https://api.shopfa.st/v1/store/team/members/string/role', {
      method: 'PUT',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        "role": "admin",
        "customRoleId": "role_0123456789abcdefghjk"
      }),
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "PUT",
        "https://api.shopfa.st/v1/store/team/members/string/role",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
        json={
          "role": "admin",
          "customRoleId": "role_0123456789abcdefghjk"
        },
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("PUT", "https://api.shopfa.st/v1/store/team/members/string/role", strings.NewReader(`{
      "role": "admin",
      "customRoleId": "role_0123456789abcdefghjk"
    }`))
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Turn Use AI on or off for a teammate (Ask AI, the AI builder and theme AI spend the store's AI credits). Only the owner

    PUT/v1/store/team/members/{userId}/ai

    Or name the store: PUT /v1/stores/{storeId}/team/members/{userId}/ai

    team:writerole: team:writesetMemberAiAccess

    Parameters

    • userIdstringpathrequired

    Body

    • enabledbooleanrequired

    Response TeamOverview

    • membersTeamMember[]required
    • invitesTeamInvite[]required
    • rolesCustomRole[]required
    • youStoreAccessrequired

    Example

    curl -X PUT "https://api.shopfa.st/v1/store/team/members/string/ai" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "enabled": false
    }'
    const res = await fetch('https://api.shopfa.st/v1/store/team/members/string/ai', {
      method: 'PUT',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        "enabled": false
      }),
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "PUT",
        "https://api.shopfa.st/v1/store/team/members/string/ai",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
        json={
          "enabled": False
        },
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("PUT", "https://api.shopfa.st/v1/store/team/members/string/ai", strings.NewReader(`{
      "enabled": false
    }`))
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Remove someone from the team and end their access at once

    DELETE/v1/store/team/members/{userId}

    Or name the store: DELETE /v1/stores/{storeId}/team/members/{userId}

    team:writerole: team:writeremoveMember

    Parameters

    • userIdstringpathrequired

    Response TeamOverview

    • membersTeamMember[]required
    • invitesTeamInvite[]required
    • rolesCustomRole[]required
    • youStoreAccessrequired

    Example

    curl -X DELETE "https://api.shopfa.st/v1/store/team/members/string" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY"
    const res = await fetch('https://api.shopfa.st/v1/store/team/members/string', {
      method: 'DELETE',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
      },
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "DELETE",
        "https://api.shopfa.st/v1/store/team/members/string",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("DELETE", "https://api.shopfa.st/v1/store/team/members/string", nil)
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Leave this store (owners transfer ownership first)

    POST/v1/store/team/leave

    Or name the store: POST /v1/stores/{storeId}/team/leave

    team:writerole: memberleaveStore

    Response Ok

    • okbooleanrequired

    Example

    curl -X POST "https://api.shopfa.st/v1/store/team/leave" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY"
    const res = await fetch('https://api.shopfa.st/v1/store/team/leave', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
      },
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "POST",
        "https://api.shopfa.st/v1/store/team/leave",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("POST", "https://api.shopfa.st/v1/store/team/leave", nil)
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Owner only: make another member the owner. You become an admin.

    POST/v1/store/team/transfer

    Or name the store: POST /v1/stores/{storeId}/team/transfer

    team:writerole: team:writetransferOwnership

    Body

    • userIdstringrequired
    • passwordstringrequired

    Response TeamOverview

    • membersTeamMember[]required
    • invitesTeamInvite[]required
    • rolesCustomRole[]required
    • youStoreAccessrequired

    Example

    curl -X POST "https://api.shopfa.st/v1/store/team/transfer" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "userId": "string",
      "password": "string"
    }'
    const res = await fetch('https://api.shopfa.st/v1/store/team/transfer', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        "userId": "string",
        "password": "string"
      }),
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "POST",
        "https://api.shopfa.st/v1/store/team/transfer",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
        json={
          "userId": "string",
          "password": "string"
        },
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("POST", "https://api.shopfa.st/v1/store/team/transfer", strings.NewReader(`{
      "userId": "string",
      "password": "string"
    }`))
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Create a custom role from the permission matrix

    POST/v1/store/team/roles

    Or name the store: POST /v1/stores/{storeId}/team/roles

    team:writerole: team:writecreateRole

    Body

    • namestringrequired
    • descriptionstringrequired
    • permissions"catalog:read" | "catalog:write" | "orders:read" | "orders:write" | "customers:read" | "customers:write" | "disputes:read" | "disputes:write" | "reviews:read" | "reviews:write" | "marketing:read" | "marketing:write" | "analytics:read" | "analytics:write" | "storefront:read" | "storefront:write" | "payments:read" | "payments:write" | "finance:read" | "finance:write" | "team:read" | "team:write" | "settings:read" | "settings:write" | "discord:read" | "discord:write" | "fraud:read" | "fraud:write" | "developers:read" | "developers:write" | "audit:read" | "audit:write" | "support:read" | "support:write" | "ai:read" | "ai:write"[]required

    Response CustomRole

    • idRoleIdrequired
    • namestringrequired
    • descriptionstringrequired
    • permissionsStorePermission[]required
    • memberCountintegerrequired
    • updatedAtTimestamprequired

    Example

    curl -X POST "https://api.shopfa.st/v1/store/team/roles" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "name": "string",
      "description": "string",
      "permissions": [
        "catalog:read"
      ]
    }'
    const res = await fetch('https://api.shopfa.st/v1/store/team/roles', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        "name": "string",
        "description": "string",
        "permissions": [
          "catalog:read"
        ]
      }),
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "POST",
        "https://api.shopfa.st/v1/store/team/roles",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
        json={
          "name": "string",
          "description": "string",
          "permissions": [
            "catalog:read"
          ]
        },
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("POST", "https://api.shopfa.st/v1/store/team/roles", strings.NewReader(`{
      "name": "string",
      "description": "string",
      "permissions": [
        "catalog:read"
      ]
    }`))
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Edit a custom role. Members with it get the new permissions on their next request.

    PUT/v1/store/team/roles/{roleId}

    Or name the store: PUT /v1/stores/{storeId}/team/roles/{roleId}

    team:writerole: team:writeupdateRole

    Parameters

    • roleIdrole_…pathrequired

    Body

    • namestringrequired
    • descriptionstringrequired
    • permissions"catalog:read" | "catalog:write" | "orders:read" | "orders:write" | "customers:read" | "customers:write" | "disputes:read" | "disputes:write" | "reviews:read" | "reviews:write" | "marketing:read" | "marketing:write" | "analytics:read" | "analytics:write" | "storefront:read" | "storefront:write" | "payments:read" | "payments:write" | "finance:read" | "finance:write" | "team:read" | "team:write" | "settings:read" | "settings:write" | "discord:read" | "discord:write" | "fraud:read" | "fraud:write" | "developers:read" | "developers:write" | "audit:read" | "audit:write" | "support:read" | "support:write" | "ai:read" | "ai:write"[]required

    Response CustomRole

    • idRoleIdrequired
    • namestringrequired
    • descriptionstringrequired
    • permissionsStorePermission[]required
    • memberCountintegerrequired
    • updatedAtTimestamprequired

    Example

    curl -X PUT "https://api.shopfa.st/v1/store/team/roles/role_0123456789abcdefghjk" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "name": "string",
      "description": "string",
      "permissions": [
        "catalog:read"
      ]
    }'
    const res = await fetch('https://api.shopfa.st/v1/store/team/roles/role_0123456789abcdefghjk', {
      method: 'PUT',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        "name": "string",
        "description": "string",
        "permissions": [
          "catalog:read"
        ]
      }),
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "PUT",
        "https://api.shopfa.st/v1/store/team/roles/role_0123456789abcdefghjk",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
        json={
          "name": "string",
          "description": "string",
          "permissions": [
            "catalog:read"
          ]
        },
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("PUT", "https://api.shopfa.st/v1/store/team/roles/role_0123456789abcdefghjk", strings.NewReader(`{
      "name": "string",
      "description": "string",
      "permissions": [
        "catalog:read"
      ]
    }`))
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Delete a custom role nobody has

    DELETE/v1/store/team/roles/{roleId}

    Or name the store: DELETE /v1/stores/{storeId}/team/roles/{roleId}

    team:writerole: team:writedeleteRole

    Parameters

    • roleIdrole_…pathrequired

    Response TeamOverview

    • membersTeamMember[]required
    • invitesTeamInvite[]required
    • rolesCustomRole[]required
    • youStoreAccessrequired

    Example

    curl -X DELETE "https://api.shopfa.st/v1/store/team/roles/role_0123456789abcdefghjk" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY"
    const res = await fetch('https://api.shopfa.st/v1/store/team/roles/role_0123456789abcdefghjk', {
      method: 'DELETE',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
      },
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "DELETE",
        "https://api.shopfa.st/v1/store/team/roles/role_0123456789abcdefghjk",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("DELETE", "https://api.shopfa.st/v1/store/team/roles/role_0123456789abcdefghjk", nil)
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Access policies, member attributes and the team's two-factor and invite settings

    GET/v1/store/team/access

    Or name the store: GET /v1/stores/{storeId}/team/access

    team:readrole: team:readgetTeamAccess

    Response TeamAccessOverview

    • policiesAccessPolicy[]required
    • settingsTeamAccessSettingsrequired
    • attributesMemberAttributes[]required
    • departmentsstring[]required
    • tagsstring[]required

    Example

    curl "https://api.shopfa.st/v1/store/team/access" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY"
    const res = await fetch('https://api.shopfa.st/v1/store/team/access', {
      method: 'GET',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
      },
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "GET",
        "https://api.shopfa.st/v1/store/team/access",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("GET", "https://api.shopfa.st/v1/store/team/access", nil)
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Add an access policy (allow policies are owner-only)

    POST/v1/store/team/policies

    Or name the store: POST /v1/stores/{storeId}/team/policies

    team:writerole: team:writecreateAccessPolicy

    Body

    • namestringrequired
    • descriptionstring
    • effect"allow" | "deny"required
    • enabledboolean
    • subjectsobjectrequired
      • everyoneboolean
      • roles"admin" | "staff" | "support" | "finance" | "custom"[]
      • customRoleIdsrole_…[]
      • userIdsusr_…[]
      • departmentsstring[]
      • tagsstring[]
    • permissions"catalog:read" | "catalog:write" | "orders:read" | "orders:write" | "customers:read" | "customers:write" | "disputes:read" | "disputes:write" | "reviews:read" | "reviews:write" | "marketing:read" | "marketing:write" | "analytics:read" | "analytics:write" | "storefront:read" | "storefront:write" | "payments:read" | "payments:write" | "finance:read" | "finance:write" | "team:read" | "team:write" | "settings:read" | "settings:write" | "discord:read" | "discord:write" | "fraud:read" | "fraud:write" | "developers:read" | "developers:write" | "audit:read" | "audit:write" | "support:read" | "support:write" | "ai:read" | "ai:write" | string[]required
    • conditionsobjectrequired
      • op"all" | "any"required
      • conditionsobject[]required
        • attribute"actor.department" | "actor.tags" | "actor.two_factor" | "actor.via_api_key" | "actor.role" | "actor.member_days" | "context.hour" | "context.weekday" | "context.ip" | "context.country" | "resource.type" | "product.type" | "product.tags" | "product.collections" | "product.price" | "product.status" | "order.total" | "order.country" | "order.status" | "order.product_types" | "order.collections" | "order.test" | "customer.country" | "store.country" | "store.region"required
        • op"eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "between" | "in" | "not_in" | "contains" | "starts_with" | "ends_with" | "in_cidr" | "not_in_cidr" | "is_true" | "is_false" | "contains_any" | "contains_none" | "is_known" | "is_unknown"required
        • valuenumber | string | string[] | null
        • value2number
      • groupsobject[]
        • op"all" | "any"required
        • conditionsobject[]required

    Response AccessPolicy

    • namestringrequired
    • descriptionstringrequired
    • effectPolicyEffectrequired
    • enabledbooleanrequired
    • subjectsPolicySubjectsrequired
    • permissionsPermissionPattern[]required
    • conditionsPolicyGrouprequired
    • idAccessPolicyIdrequired
    • createdBystringrequired
    • createdAtTimestamprequired
    • updatedAtTimestamprequired

    Example

    curl -X POST "https://api.shopfa.st/v1/store/team/policies" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "name": "string",
      "description": "",
      "effect": "allow",
      "enabled": true,
      "subjects": {},
      "permissions": [
        "catalog:read"
      ],
      "conditions": {
        "op": "all",
        "conditions": [
          {
            "attribute": "actor.department",
            "op": "eq"
          }
        ]
      }
    }'
    const res = await fetch('https://api.shopfa.st/v1/store/team/policies', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        "name": "string",
        "description": "",
        "effect": "allow",
        "enabled": true,
        "subjects": {},
        "permissions": [
          "catalog:read"
        ],
        "conditions": {
          "op": "all",
          "conditions": [
            {
              "attribute": "actor.department",
              "op": "eq"
            }
          ]
        }
      }),
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "POST",
        "https://api.shopfa.st/v1/store/team/policies",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
        json={
          "name": "string",
          "description": "",
          "effect": "allow",
          "enabled": True,
          "subjects": {},
          "permissions": [
            "catalog:read"
          ],
          "conditions": {
            "op": "all",
            "conditions": [
              {
                "attribute": "actor.department",
                "op": "eq"
              }
            ]
          }
        },
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("POST", "https://api.shopfa.st/v1/store/team/policies", strings.NewReader(`{
      "name": "string",
      "description": "",
      "effect": "allow",
      "enabled": true,
      "subjects": {},
      "permissions": [
        "catalog:read"
      ],
      "conditions": {
        "op": "all",
        "conditions": [
          {
            "attribute": "actor.department",
            "op": "eq"
          }
        ]
      }
    }`))
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Change an access policy

    PUT/v1/store/team/policies/{policyId}

    Or name the store: PUT /v1/stores/{storeId}/team/policies/{policyId}

    team:writerole: team:writeupdateAccessPolicy

    Parameters

    • policyIdpol_…pathrequired

    Body

    • namestringrequired
    • descriptionstring
    • effect"allow" | "deny"required
    • enabledboolean
    • subjectsobjectrequired
      • everyoneboolean
      • roles"admin" | "staff" | "support" | "finance" | "custom"[]
      • customRoleIdsrole_…[]
      • userIdsusr_…[]
      • departmentsstring[]
      • tagsstring[]
    • permissions"catalog:read" | "catalog:write" | "orders:read" | "orders:write" | "customers:read" | "customers:write" | "disputes:read" | "disputes:write" | "reviews:read" | "reviews:write" | "marketing:read" | "marketing:write" | "analytics:read" | "analytics:write" | "storefront:read" | "storefront:write" | "payments:read" | "payments:write" | "finance:read" | "finance:write" | "team:read" | "team:write" | "settings:read" | "settings:write" | "discord:read" | "discord:write" | "fraud:read" | "fraud:write" | "developers:read" | "developers:write" | "audit:read" | "audit:write" | "support:read" | "support:write" | "ai:read" | "ai:write" | string[]required
    • conditionsobjectrequired
      • op"all" | "any"required
      • conditionsobject[]required
        • attribute"actor.department" | "actor.tags" | "actor.two_factor" | "actor.via_api_key" | "actor.role" | "actor.member_days" | "context.hour" | "context.weekday" | "context.ip" | "context.country" | "resource.type" | "product.type" | "product.tags" | "product.collections" | "product.price" | "product.status" | "order.total" | "order.country" | "order.status" | "order.product_types" | "order.collections" | "order.test" | "customer.country" | "store.country" | "store.region"required
        • op"eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "between" | "in" | "not_in" | "contains" | "starts_with" | "ends_with" | "in_cidr" | "not_in_cidr" | "is_true" | "is_false" | "contains_any" | "contains_none" | "is_known" | "is_unknown"required
        • valuenumber | string | string[] | null
        • value2number
      • groupsobject[]
        • op"all" | "any"required
        • conditionsobject[]required

    Response AccessPolicy

    • namestringrequired
    • descriptionstringrequired
    • effectPolicyEffectrequired
    • enabledbooleanrequired
    • subjectsPolicySubjectsrequired
    • permissionsPermissionPattern[]required
    • conditionsPolicyGrouprequired
    • idAccessPolicyIdrequired
    • createdBystringrequired
    • createdAtTimestamprequired
    • updatedAtTimestamprequired

    Example

    curl -X PUT "https://api.shopfa.st/v1/store/team/policies/pol_0123456789abcdefghjk" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "name": "string",
      "description": "",
      "effect": "allow",
      "enabled": true,
      "subjects": {},
      "permissions": [
        "catalog:read"
      ],
      "conditions": {
        "op": "all",
        "conditions": [
          {
            "attribute": "actor.department",
            "op": "eq"
          }
        ]
      }
    }'
    const res = await fetch('https://api.shopfa.st/v1/store/team/policies/pol_0123456789abcdefghjk', {
      method: 'PUT',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        "name": "string",
        "description": "",
        "effect": "allow",
        "enabled": true,
        "subjects": {},
        "permissions": [
          "catalog:read"
        ],
        "conditions": {
          "op": "all",
          "conditions": [
            {
              "attribute": "actor.department",
              "op": "eq"
            }
          ]
        }
      }),
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "PUT",
        "https://api.shopfa.st/v1/store/team/policies/pol_0123456789abcdefghjk",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
        json={
          "name": "string",
          "description": "",
          "effect": "allow",
          "enabled": True,
          "subjects": {},
          "permissions": [
            "catalog:read"
          ],
          "conditions": {
            "op": "all",
            "conditions": [
              {
                "attribute": "actor.department",
                "op": "eq"
              }
            ]
          }
        },
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("PUT", "https://api.shopfa.st/v1/store/team/policies/pol_0123456789abcdefghjk", strings.NewReader(`{
      "name": "string",
      "description": "",
      "effect": "allow",
      "enabled": true,
      "subjects": {},
      "permissions": [
        "catalog:read"
      ],
      "conditions": {
        "op": "all",
        "conditions": [
          {
            "attribute": "actor.department",
            "op": "eq"
          }
        ]
      }
    }`))
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Delete an access policy

    DELETE/v1/store/team/policies/{policyId}

    Or name the store: DELETE /v1/stores/{storeId}/team/policies/{policyId}

    team:writerole: team:writedeleteAccessPolicy

    Parameters

    • policyIdpol_…pathrequired

    Response Ok

    • okbooleanrequired

    Example

    curl -X DELETE "https://api.shopfa.st/v1/store/team/policies/pol_0123456789abcdefghjk" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY"
    const res = await fetch('https://api.shopfa.st/v1/store/team/policies/pol_0123456789abcdefghjk', {
      method: 'DELETE',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
      },
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "DELETE",
        "https://api.shopfa.st/v1/store/team/policies/pol_0123456789abcdefghjk",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("DELETE", "https://api.shopfa.st/v1/store/team/policies/pol_0123456789abcdefghjk", nil)
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    What a member (or a role) could do, here and now or in a given context, with every policy explained

    POST/v1/store/team/simulate

    Or name the store: POST /v1/stores/{storeId}/team/simulate

    team:writerole: team:readsimulateAccess

    Body

    • userIdusr_… | null
    • assignmentobject | null
    • departmentstring | null
    • tagsstring[] | null
    • twoFactorboolean
    • viaApiKeyboolean
    • permission"catalog:read" | "catalog:write" | "orders:read" | "orders:write" | "customers:read" | "customers:write" | "disputes:read" | "disputes:write" | "reviews:read" | "reviews:write" | "marketing:read" | "marketing:write" | "analytics:read" | "analytics:write" | "storefront:read" | "storefront:write" | "payments:read" | "payments:write" | "finance:read" | "finance:write" | "team:read" | "team:write" | "settings:read" | "settings:write" | "discord:read" | "discord:write" | "fraud:read" | "fraud:write" | "developers:read" | "developers:write" | "audit:read" | "audit:write" | "support:read" | "support:write" | "ai:read" | "ai:write" | null
    • endpointstring | null
    • resourceobject | null
    • attributesobject
    • contextobject
      • hourinteger | null
      • weekdayinteger | null
      • ipstring | null
      • countrystring | null
    • policiesobject[] | null

    Response AccessSimulationResult

    • subjectobjectrequired
      • namestringrequired
      • roleNamestringrequired
      • departmentstringrequired
      • tagsstring[]required
      • twoFactorbooleanrequired
    • attributesAttributeSnapshotrequired
    • decisionAccessDecision | nullrequired
    • matrixobject[]required
      • permissionStorePermissionrequired
      • allowedbooleanrequired
      • decidedByAccessDecidedByrequired
      • policystringrequired

    Example

    curl -X POST "https://api.shopfa.st/v1/store/team/simulate" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "userId": null,
      "assignment": null,
      "department": null,
      "tags": null,
      "twoFactor": null,
      "viaApiKey": false,
      "permission": null,
      "endpoint": null,
      "resource": null,
      "attributes": {},
      "context": {
        "hour": null,
        "weekday": null,
        "ip": null,
        "country": null
      },
      "policies": null
    }'
    const res = await fetch('https://api.shopfa.st/v1/store/team/simulate', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        "userId": null,
        "assignment": null,
        "department": null,
        "tags": null,
        "twoFactor": null,
        "viaApiKey": false,
        "permission": null,
        "endpoint": null,
        "resource": null,
        "attributes": {},
        "context": {
          "hour": null,
          "weekday": null,
          "ip": null,
          "country": null
        },
        "policies": null
      }),
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "POST",
        "https://api.shopfa.st/v1/store/team/simulate",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
        json={
          "userId": None,
          "assignment": None,
          "department": None,
          "tags": None,
          "twoFactor": None,
          "viaApiKey": False,
          "permission": None,
          "endpoint": None,
          "resource": None,
          "attributes": {},
          "context": {
            "hour": None,
            "weekday": None,
            "ip": None,
            "country": None
          },
          "policies": None
        },
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("POST", "https://api.shopfa.st/v1/store/team/simulate", strings.NewReader(`{
      "userId": null,
      "assignment": null,
      "department": null,
      "tags": null,
      "twoFactor": null,
      "viaApiKey": false,
      "permission": null,
      "endpoint": null,
      "resource": null,
      "attributes": {},
      "context": {
        "hour": null,
        "weekday": null,
        "ip": null,
        "country": null
      },
      "policies": null
    }`))
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Which roles need two-factor sign-in, and how long invite links work

    PUT/v1/store/team/access-settings

    Or name the store: PUT /v1/stores/{storeId}/team/access-settings

    team:writerole: team:writeupdateTeamAccessSettings

    Body

    • require2faRoles"admin" | "staff" | "support" | "finance" | role_…[]required
    • inviteExpiryHoursintegerrequired

    Response TeamAccessSettings

    • require2faRolesRoleKey[]required
    • inviteExpiryHoursintegerrequired

    Example

    curl -X PUT "https://api.shopfa.st/v1/store/team/access-settings" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "require2faRoles": [
        "admin"
      ],
      "inviteExpiryHours": 1
    }'
    const res = await fetch('https://api.shopfa.st/v1/store/team/access-settings', {
      method: 'PUT',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        "require2faRoles": [
          "admin"
        ],
        "inviteExpiryHours": 1
      }),
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "PUT",
        "https://api.shopfa.st/v1/store/team/access-settings",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
        json={
          "require2faRoles": [
            "admin"
          ],
          "inviteExpiryHours": 1
        },
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("PUT", "https://api.shopfa.st/v1/store/team/access-settings", strings.NewReader(`{
      "require2faRoles": [
        "admin"
      ],
      "inviteExpiryHours": 1
    }`))
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Set a teammate's department and tags (used by access policies)

    PUT/v1/store/team/members/{userId}/attributes

    Or name the store: PUT /v1/stores/{storeId}/team/members/{userId}/attributes

    team:writerole: team:writeupdateMemberAttributes

    Parameters

    • userIdusr_…pathrequired

    Body

    • departmentstring | nullrequired
    • tagsstring[]required

    Response MemberAttributes

    • userIdUserIdrequired
    • departmentstring | nullrequired
    • tagsstring[]required

    Example

    curl -X PUT "https://api.shopfa.st/v1/store/team/members/usr_0123456789abcdefghjk/attributes" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "department": "string",
      "tags": [
        "string"
      ]
    }'
    const res = await fetch('https://api.shopfa.st/v1/store/team/members/usr_0123456789abcdefghjk/attributes', {
      method: 'PUT',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        "department": "string",
        "tags": [
          "string"
        ]
      }),
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "PUT",
        "https://api.shopfa.st/v1/store/team/members/usr_0123456789abcdefghjk/attributes",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
        json={
          "department": "string",
          "tags": [
            "string"
          ]
        },
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("PUT", "https://api.shopfa.st/v1/store/team/members/usr_0123456789abcdefghjk/attributes", strings.NewReader(`{
      "department": "string",
      "tags": [
        "string"
      ]
    }`))
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Invite up to 200 people at once, each with a role and the same attributes

    POST/v1/store/team/invites/bulk

    Or name the store: POST /v1/stores/{storeId}/team/invites/bulk

    team:writerole: team:writebulkInviteMembers

    Body

    • departmentstring | null
    • tagsstring[]
    • expiresInHoursinteger | null
    • entriesobject[]required
      • emailstringrequired
      • assignmentobject | null
    • assignmentobjectrequired
      • role"admin" | "staff" | "support" | "finance" | "custom"required
      • customRoleIdrole_… | nullrequired

    Response BulkInviteResult

    • invitedTeamInvite[]required
    • skippedobject[]required
      • emailstringrequired
      • reasonstringrequired

    Example

    curl -X POST "https://api.shopfa.st/v1/store/team/invites/bulk" \
      -H "Authorization: Bearer $SHOPFAST_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "department": null,
      "tags": [],
      "expiresInHours": null,
      "entries": [
        {
          "email": "[email protected]"
        }
      ],
      "assignment": {
        "role": "admin",
        "customRoleId": "role_0123456789abcdefghjk"
      }
    }'
    const res = await fetch('https://api.shopfa.st/v1/store/team/invites/bulk', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.SHOPFAST_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        "department": null,
        "tags": [],
        "expiresInHours": null,
        "entries": [
          {
            "email": "[email protected]"
          }
        ],
        "assignment": {
          "role": "admin",
          "customRoleId": "role_0123456789abcdefghjk"
        }
      }),
    });
    if (!res.ok) throw new Error((await res.json()).detail);
    const data = await res.json();
    import os, requests
    
    res = requests.request(
        "POST",
        "https://api.shopfa.st/v1/store/team/invites/bulk",
        headers={"Authorization": f"Bearer {os.environ['SHOPFAST_API_KEY']}"},
        json={
          "department": None,
          "tags": [],
          "expiresInHours": None,
          "entries": [
            {
              "email": "[email protected]"
            }
          ],
          "assignment": {
            "role": "admin",
            "customRoleId": "role_0123456789abcdefghjk"
          }
        },
    )
    res.raise_for_status()
    data = res.json()
    req, _ := http.NewRequest("POST", "https://api.shopfa.st/v1/store/team/invites/bulk", strings.NewReader(`{
      "department": null,
      "tags": [],
      "expiresInHours": null,
      "entries": [
        {
          "email": "[email protected]"
        }
      ],
      "assignment": {
        "role": "admin",
        "customRoleId": "role_0123456789abcdefghjk"
      }
    }`))
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SHOPFAST_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    res, err := http.DefaultClient.Do(req)
    Try it with your key

    Use a test key on a development store. The key stays in this tab (sessionStorage) and is sent only to the base URL above.

    Was this page helpful?