curl --request POST \
--url https://api.sand.etherfuse.com/organization/{organizationId}/member \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"email": "[email protected]",
"role": "admin",
"emailInviteLink": "https://partner.example.com/kyb-invite?org=a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
'const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
email: '[email protected]',
role: 'admin',
emailInviteLink: 'https://partner.example.com/kyb-invite?org=a1b2c3d4-e5f6-7890-abcd-ef1234567890'
})
};
fetch('https://api.sand.etherfuse.com/organization/{organizationId}/member', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.sand.etherfuse.com/organization/{organizationId}/member"
payload = {
"email": "[email protected]",
"role": "admin",
"emailInviteLink": "https://partner.example.com/kyb-invite?org=a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"members": [
{
"memberId": "9f1c4b2a-7d3e-4c5f-8a6b-1e2d3c4b5a6f",
"email": "[email protected]",
"role": "admin",
"joinedAt": "2026-06-17T00:00:00Z"
}
],
"invited": [
{
"email": "[email protected]",
"role": "member",
"invitedAt": "2026-06-17T00:00:00Z"
}
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}Add organization member
Adds a person to a customer business organization, by email or memberId. A memberId is the sub you sign into the person’s JWT. Members sign in with that JWT and complete the organization’s KYB.
- By
email: if the email belongs to someone who already signed in through your JWT, they become a member at once. Otherwise we create a pending invite, accepted the first time that email signs in with yourkybJWT. SendemailInviteLinkto have us email them that link, or leave it out and tell them yourself. - By
memberId: adds someone by theirsub, and sends no email. Thesubexists once that person has exchanged a JWT with POST /auth/token or been launched. An unknownsubreturns404, and a business organization’s id is rejected.
Adding someone who was removed earlier brings them back. Adding a current member returns 409 conflict. The response lists the members and invites: someone added at once is under members, an invite is under invited.
Your own organization’s members are managed in the Etherfuse portal, so naming it returns 403 forbidden. A personal organization has no members and returns 400 invalid-request.
curl --request POST \
--url https://api.sand.etherfuse.com/organization/{organizationId}/member \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"email": "[email protected]",
"role": "admin",
"emailInviteLink": "https://partner.example.com/kyb-invite?org=a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
'const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
email: '[email protected]',
role: 'admin',
emailInviteLink: 'https://partner.example.com/kyb-invite?org=a1b2c3d4-e5f6-7890-abcd-ef1234567890'
})
};
fetch('https://api.sand.etherfuse.com/organization/{organizationId}/member', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.sand.etherfuse.com/organization/{organizationId}/member"
payload = {
"email": "[email protected]",
"role": "admin",
"emailInviteLink": "https://partner.example.com/kyb-invite?org=a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"members": [
{
"memberId": "9f1c4b2a-7d3e-4c5f-8a6b-1e2d3c4b5a6f",
"email": "[email protected]",
"role": "admin",
"joinedAt": "2026-06-17T00:00:00Z"
}
],
"invited": [
{
"email": "[email protected]",
"role": "member",
"invitedAt": "2026-06-17T00:00:00Z"
}
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}Authorizations
API key sent in the Authorization header, with no Bearer prefix.
Path Parameters
The organization this call acts for: your API key's organization or one of its customer organizations. Any other id returns 404 not-found.
Body
The member's role in the organization.
admin, member Invite or add a member by email address. If the email matches a user who has already signed in through your JWT, they're added as a member immediately; otherwise a pending invite is created and accepted automatically the first time that email signs in via your kyb JWT. Use email when you don't have the person's memberId yet, or when you want Etherfuse to email them an invite (see emailInviteLink). Send exactly one of email or memberId.
Add someone directly by their sub (the value you put in the JWT sub when they sign in); no email is sent. The person must already exist, which happens the first time they exchange a JWT via POST /auth/token (or are launched); an unknown sub returns 404. A business organization's id is rejected. Send exactly one of email or memberId.
Optional. When adding by email and a pending invite is created (the email isn't already a member), Etherfuse emails them this URL as-is (you control the full link, including any query params) as the call to action. Omit it to create the invite silently and notify the user yourself. Ignored when the email already matches a member who is added immediately.