Merchant Service API
The Merchant Service manages business accounts, team members, and merchant configurations. It provides multi-merchant support, role-based team management, and centralized settings control.
Base URL: https://paymentgateway.redahaloubi.com/api/v1All endpoints require JWT authentication unless noted otherwise.
Authentication
All Merchant API endpoints require authentication via JWT Bearer token:
Authorization : Bearer {access_token}
Permission Requirements: Most endpoints also require specific permissions based on your role in the merchant:
Read operations: All team members
Create operations: Owner, Admin, Manager
Update operations: Owner, Admin
Delete operations: Owner only
Rate Limits
Standard Endpoints 100 requests per second per userApplied to most merchant operations
Team Management 20 requests per second per merchantInvitation and team modification endpoints
Merchant Endpoints
Create Merchant
Create a new merchant account. Users can only create one merchant account. The user becomes the Owner with full access.
Request Body
Public-facing business name Example: “Acme Corporation”
Legal business name (if different from business name) Example: “Acme Corp LLC”
Business contact email Format: Valid email address
Business phone number Example: “+1-555-123-4567”
Type of business entity Options: individual, sole_proprietor, partnership, corporation, non_profit
Example Request
curl -X POST https://paymentgateway.redahaloubi.com/api/v1/merchants \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{
"business_name": "Acme Corporation",
"legal_name": "Acme Corp LLC",
"email": "[email protected] ",
"phone": "+1-555-123-4567",
"website": "https://acme.com",
"business_type": "corporation"
}'
Response (201 Created)
{
"success" : true ,
"data" : {
"merchant" : {
"id" : "550e8400-e29b-41d4-a716-446655440000" ,
"merchant_code" : "mch_abc123def456" ,
"owner_id" : "user_abc123" ,
"business_name" : "Acme Corporation" ,
"legal_name" : "Acme Corp LLC" ,
"email" : "[email protected] " ,
"phone" : "+1-555-123-4567" ,
"website" : "https://acme.com" ,
"status" : "pending_review" ,
"business_type" : "corporation" ,
"country_code" : "US" ,
"currency_code" : "USD" ,
"timezone" : "America/New_York" ,
"created_at" : "2026-01-24T10:00:00Z" ,
"updated_at" : "2026-01-24T10:00:00Z"
}
},
"message" : "Merchant created successfully"
}
409 Conflict - User Already Has Merchant {
"success" : false ,
"error" : "user already has a merchant"
}
400 Bad Request - Invalid Business Type {
"success" : false ,
"error" : "business_type must be one of: individual, sole_proprietor, partnership, corporation, non_profit"
}
400 Bad Request - Invalid Email {
"success" : false ,
"error" : "email must be a valid email address"
}
Merchant Status:
pending_review: Newly created, awaiting verification
active: Verified and can process payments
suspended: Temporarily disabled
closed: Permanently deactivated
List User Merchants
Get all merchants where the authenticated user is a team member (including owned merchants).
Example Request
curl -X GET https://paymentgateway.redahaloubi.com/api/v1/merchants \
-H "Authorization: Bearer {access_token}"
Response (200 OK)
{
"success" : true ,
"data" : {
"merchants" : [
{
"id" : "merchant_abc123" ,
"merchant_code" : "mch_abc123def456" ,
"owner_id" : "user_abc123" ,
"business_name" : "Acme Corporation" ,
"legal_name" : "Acme Corp LLC" ,
"email" : "[email protected] " ,
"phone" : "+1-555-123-4567" ,
"website" : "https://acme.com" ,
"status" : "active" ,
"business_type" : "corporation" ,
"country_code" : "US" ,
"currency_code" : "USD" ,
"timezone" : "America/New_York" ,
"created_at" : "2026-01-24T10:00:00Z" ,
"updated_at" : "2026-01-24T10:00:00Z"
},
{
"id" : "merchant_xyz789" ,
"merchant_code" : "mch_xyz789uvw012" ,
"owner_id" : "user_def456" ,
"business_name" : "Tech Startup Inc" ,
"email" : "[email protected] " ,
"status" : "active" ,
"business_type" : "corporation" ,
"created_at" : "2026-01-20T14:00:00Z" ,
"updated_at" : "2026-01-23T09:30:00Z"
}
],
"count" : 2
}
}
Multi-Merchant Support: Users can be members of multiple merchants with different roles. The response includes all merchants where the user has any level of access.
Get Merchant
Get basic information about a specific merchant.
Path Parameters
Required Permission: read in the merchant
Example Request
curl -X GET https://paymentgateway.redahaloubi.com/api/v1/merchants/{merchant_id} \
-H "Authorization: Bearer {access_token}"
Response (200 OK)
{
"success" : true ,
"data" : {
"merchant" : {
"id" : "merchant_abc123" ,
"merchant_code" : "mch_abc123def456" ,
"owner_id" : "user_abc123" ,
"business_name" : "Acme Corporation" ,
"legal_name" : "Acme Corp LLC" ,
"email" : "[email protected] " ,
"phone" : "+1-555-123-4567" ,
"website" : "https://acme.com" ,
"status" : "active" ,
"business_type" : "corporation" ,
"country_code" : "US" ,
"currency_code" : "USD" ,
"timezone" : "America/New_York" ,
"created_at" : "2026-01-24T10:00:00Z" ,
"updated_at" : "2026-01-24T10:00:00Z"
}
}
}
403 Forbidden - Access Denied {
"success" : false ,
"error" : "access denied"
}
404 Not Found {
"success" : false ,
"error" : "merchant not found"
}
Get Merchant Details
Get comprehensive merchant information including settings, business info, branding, and verification status.
Path Parameters
Required Permission: read in the merchant
Example Request
curl -X GET https://paymentgateway.redahaloubi.com/api/v1/merchants/{merchant_id}/details \
-H "Authorization: Bearer {access_token}"
Response (200 OK)
{
"success" : true ,
"data" : {
"merchant" : {
"id" : "merchant_abc123" ,
"merchant_code" : "mch_abc123def456" ,
"business_name" : "Acme Corporation" ,
"status" : "active" ,
"created_at" : "2026-01-24T10:00:00Z"
},
"settings" : {
"default_currency" : "USD" ,
"auto_settle" : true ,
"settle_schedule" : "daily" ,
"webhook_url" : "https://acme.com/webhooks/payment" ,
"notification_email" : "[email protected] " ,
"send_email_receipts" : true
},
"business_info" : {
"address_line1" : "123 Main St" ,
"address_line2" : "Suite 100" ,
"city" : "San Francisco" ,
"state" : "CA" ,
"postal_code" : "94102" ,
"country" : "US" ,
"tax_id" : "12-3456789"
},
"branding" : {
"logo_url" : "https://cdn.acme.com/logo.png" ,
"brand_color" : "#FF6B35" ,
"favicon_url" : "https://cdn.acme.com/favicon.ico"
},
"verification" : {
"status" : "verified" ,
"verified_at" : "2026-01-25T08:00:00Z" ,
"kyc_status" : "approved" ,
"document_status" : "approved"
}
}
}
Update Merchant
Update merchant information. Only specified fields will be updated.
Path Parameters
Required Permission: update (Owner or Admin)
Request Body
Updated business email Format: Valid email address
Example Request
curl -X PATCH https://paymentgateway.redahaloubi.com/api/v1/merchants/{merchant_id} \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{
"business_name": "Acme Inc",
"website": "https://acmeinc.com"
}'
Response (200 OK)
{
"success" : true ,
"message" : "Merchant updated successfully"
}
403 Forbidden - Insufficient Permissions {
"success" : false ,
"error" : "access denied"
}
400 Bad Request - Invalid Email {
"success" : false ,
"error" : "email must be a valid email address"
}
Delete Merchant
Soft delete a merchant account. This action can only be performed by the Owner.
Path Parameters
Required Permission: delete (Owner only)
Example Request
curl -X DELETE https://paymentgateway.redahaloubi.com/api/v1/merchants/{merchant_id} \
-H "Authorization: Bearer {access_token}"
Response (200 OK)
{
"success" : true ,
"message" : "Merchant deleted successfully"
}
Soft Delete: Merchants are soft-deleted, meaning:
Data is not permanently removed
Account can be restored by support
All team members lose access immediately
Active subscriptions/payments are cancelled
API keys are immediately deactivated
403 Forbidden - Only Owner Can Delete {
"success" : false ,
"error" : "only the merchant owner can delete the merchant"
}
Team Management Endpoints
Get Team Members
List all team members in a merchant with their roles and status.
Path Parameters
Required Permission: read in the merchant
Example Request
curl -X GET https://paymentgateway.redahaloubi.com/api/v1/merchants/{merchant_id}/team \
-H "Authorization: Bearer {access_token}"
Response (200 OK)
{
"success" : true ,
"data" : {
"team_members" : [
{
"id" : "member_abc123" ,
"user_id" : "user_abc123" ,
"email" : "[email protected] " ,
"name" : "John Doe" ,
"role_id" : "role_owner_123" ,
"role_name" : "Owner" ,
"status" : "active" ,
"joined_at" : "2026-01-24T10:00:00Z" ,
"last_active_at" : "2026-01-25T15:30:00Z"
},
{
"id" : "member_def456" ,
"user_id" : "user_def456" ,
"email" : "[email protected] " ,
"name" : "Jane Smith" ,
"role_id" : "role_admin_456" ,
"role_name" : "Admin" ,
"status" : "active" ,
"joined_at" : "2026-01-25T09:00:00Z" ,
"last_active_at" : "2026-01-25T14:45:00Z"
},
{
"id" : "member_ghi789" ,
"user_id" : "user_ghi789" ,
"email" : "[email protected] " ,
"name" : "Bob Johnson" ,
"role_id" : "role_staff_012" ,
"role_name" : "Staff" ,
"status" : "pending" ,
"joined_at" : null ,
"invited_at" : "2026-01-25T10:00:00Z"
}
],
"count" : 3
}
}
Team Member Status:
active: User has accepted invitation and has access
pending: Invitation sent but not yet accepted
suspended: Access temporarily revoked
Invite Team Member
/merchants/:id/team/invite
Send an invitation to join the merchant team. The invitee receives an email with an invitation token.
Path Parameters
Required Permission: create (Owner, Admin, or Manager)
Request Body
Email address of the person to invite Format: Valid email address
Role ID to assign (from Auth Service roles) Format: UUID
Role name for display Options: Owner, Admin, Manager, Staff
Example Request
curl -X POST https://paymentgateway.redahaloubi.com/api/v1/merchants/{merchant_id}/team/invite \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected] ",
"role_id": "role_manager_789",
"role_name": "Manager"
}'
Response (201 Created)
{
"success" : true ,
"data" : {
"invitation" : {
"id" : "invitation_abc123" ,
"email" : "[email protected] " ,
"status" : "pending" ,
"role_name" : "Manager" ,
"invitation_token" : "inv_abc123def456ghi789jkl012" ,
"expires_at" : "2026-01-31T10:00:00Z" ,
"created_at" : "2026-01-24T10:00:00Z"
}
},
"message" : "Invitation sent successfully"
}
400 Bad Request - User Already in Team {
"success" : false ,
"error" : "user is already a member of this merchant"
}
400 Bad Request - Pending Invitation Exists {
"success" : false ,
"error" : "pending invitation already exists for this email"
}
403 Forbidden - Insufficient Permissions {
"success" : false ,
"error" : "you do not have permission to invite team members"
}
Invitation Lifecycle:
Invitations expire after 7 days
User must have an account to accept (or register first)
One invitation per email per merchant at a time
Invitation token is single-use
Accept Invitation
/invitations/:token/accept
Accept a team invitation using the invitation token received via email.
Path Parameters
Invitation token from email Example: inv_abc123def456ghi789jkl012
Example Request
curl -X POST https://paymentgateway.redahaloubi.com/api/v1/invitations/inv_abc123def456/accept \
-H "Authorization: Bearer {access_token}"
Response (200 OK)
{
"success" : true ,
"message" : "Invitation accepted successfully"
}
400 Bad Request - Invalid Token {
"success" : false ,
"error" : "invalid or expired invitation token"
}
400 Bad Request - Email Mismatch {
"success" : false ,
"error" : "invitation email does not match your account email"
}
409 Conflict - Already Accepted {
"success" : false ,
"error" : "invitation has already been accepted"
}
Update Team Member Role
/merchants/:id/team/:user_id
Change a team member’s role. Cannot modify the Owner’s role.
Path Parameters
User ID of the team member to update (UUID)
Required Permission: update (Owner or Admin)
Request Body
New role name Options: Admin, Manager, Staff
Example Request
curl -X PATCH https://paymentgateway.redahaloubi.com/api/v1/merchants/{merchant_id}/team/{user_id} \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{
"role_id": "role_admin_456",
"role_name": "Admin"
}'
Response (200 OK)
{
"success" : true ,
"message" : "Team member role updated successfully"
}
400 Bad Request - Cannot Modify Owner {
"success" : false ,
"error" : "cannot modify the owner's role"
}
403 Forbidden - Insufficient Permissions {
"success" : false ,
"error" : "only owner and admin can update team member roles"
}
Remove Team Member
/merchants/:id/team/:user_id
Remove a team member from the merchant. Cannot remove the Owner.
Path Parameters
User ID of the team member to remove (UUID)
Required Permission: delete (Owner only)
Example Request
curl -X DELETE https://paymentgateway.redahaloubi.com/api/v1/merchants/{merchant_id}/team/{user_id} \
-H "Authorization: Bearer {access_token}"
Response (200 OK)
{
"success" : true ,
"message" : "Team member removed successfully"
}
400 Bad Request - Cannot Remove Owner {
"success" : false ,
"error" : "cannot remove the merchant owner"
}
403 Forbidden - Only Owner Can Remove {
"success" : false ,
"error" : "only the owner can remove team members"
}
Immediate Effect: Removing a team member immediately revokes all access to the merchant, including:
Dashboard access
API permissions
Payment data visibility
Reports and analytics
Get Pending Invitations
/merchants/:id/invitations
List all pending (not yet accepted) invitations for a merchant.
Path Parameters
Required Permission: read in the merchant
Example Request
curl -X GET https://paymentgateway.redahaloubi.com/api/v1/merchants/{merchant_id}/invitations \
-H "Authorization: Bearer {access_token}"
Response (200 OK)
{
"success" : true ,
"data" : {
"invitations" : [
{
"id" : "invitation_abc123" ,
"email" : "[email protected] " ,
"role_name" : "Manager" ,
"status" : "pending" ,
"invited_by" : "user_abc123" ,
"invited_by_name" : "John Doe" ,
"created_at" : "2026-01-24T10:00:00Z" ,
"expires_at" : "2026-01-31T10:00:00Z"
},
{
"id" : "invitation_def456" ,
"email" : "[email protected] " ,
"role_name" : "Staff" ,
"status" : "pending" ,
"invited_by" : "user_abc123" ,
"invited_by_name" : "John Doe" ,
"created_at" : "2026-01-25T09:00:00Z" ,
"expires_at" : "2026-02-01T09:00:00Z"
}
],
"count" : 2
}
}
Cancel Invitation
Cancel a pending invitation before it’s accepted.
Path Parameters
Required Permission: delete (Owner) or invitation creator
Example Request
curl -X DELETE https://paymentgateway.redahaloubi.com/api/v1/invitations/{invitation_id} \
-H "Authorization: Bearer {access_token}"
Response (200 OK)
{
"success" : true ,
"message" : "Invitation cancelled successfully"
}
400 Bad Request - Already Accepted {
"success" : false ,
"error" : "cannot cancel an accepted invitation"
}
403 Forbidden {
"success" : false ,
"error" : "only the invitation creator or owner can cancel invitations"
}
Settings Endpoints
Get Settings
Get merchant settings including payment configuration, webhooks, and preferences.
Path Parameters
Required Permission: read in the merchant
Example Request
curl -X GET https://paymentgateway.redahaloubi.com/api/v1/merchants/{merchant_id}/settings \
-H "Authorization: Bearer {access_token}"
Response (200 OK)
{
"success" : true ,
"data" : {
"settings" : {
"id" : "settings_abc123" ,
"merchant_id" : "merchant_abc123" ,
"default_currency" : "USD" ,
"auto_settle" : true ,
"settle_schedule" : "daily" ,
"webhook_url" : "https://acme.com/webhooks/payment" ,
"webhook_secret" : "whsec_abc123def456" ,
"notification_email" : "[email protected] " ,
"send_email_receipts" : true ,
"receipt_email_from" : "[email protected] " ,
"payment_methods_enabled" : [ "card" , "bank_transfer" ],
"supported_currencies" : [ "USD" , "EUR" , "MAD" ],
"created_at" : "2026-01-24T10:00:00Z" ,
"updated_at" : "2026-01-25T14:30:00Z"
}
}
}
Update Settings
Update merchant settings. Only specified fields will be updated.
Path Parameters
Required Permission: update (Owner or Admin)
Request Body
Default currency for transactions Format: ISO 4217 currency code (3 letters)Example: “USD”, “EUR”, “MAD”
Enable automatic settlement Default: true
Settlement frequency Options: daily, weekly, monthly
URL to receive webhook notifications Format: Valid HTTPS URL
Email for important notifications Format: Valid email address
Send email receipts to customers Default: true
Example Request
curl -X PATCH https://paymentgateway.redahaloubi.com/api/v1/merchants/{merchant_id}/settings \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{
"default_currency": "EUR",
"webhook_url": "https://acme.com/api/webhooks",
"auto_settle": false
}'
Response (200 OK)
{
"success" : true ,
"message" : "Settings updated successfully"
}
400 Bad Request - Invalid Currency {
"success" : false ,
"error" : "default_currency must be exactly 3 characters"
}
400 Bad Request - Invalid Webhook URL {
"success" : false ,
"error" : "webhook_url must be a valid URL"
}
400 Bad Request - Invalid Schedule {
"success" : false ,
"error" : "settle_schedule must be one of: daily, weekly, monthly"
}
Webhook Configuration: When setting a webhook URL, the system will:
Automatically generate a webhook secret (whsec_...)
Send a test webhook to verify the endpoint
Store the secret for HMAC signature verification
Include the webhook secret in your webhook handler to verify authenticity.
API Key Endpoints
API Key Management: These endpoints are in the Merchant Service but communicate with the Auth Service for actual key creation and storage. They require Owner permissions.
Create API Key
Generate a new API key for payment processing. Requires Owner permissions.
Request Body
Merchant ID for which to create the API key (UUID)
Descriptive name for the API key Example: “Production Server”, “Staging Environment”
Example Request
curl -X POST https://paymentgateway.redahaloubi.com/api/v1/merchants/api-keys \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{
"merchant_id": "merchant_abc123",
"name": "Production API Key"
}'
Response (201 Created)
{
"success" : true ,
"data" : {
"api_key" : {
"id" : "apikey_abc123" ,
"name" : "Production API Key" ,
"key_prefix" : "pk_live_" ,
"created_at" : "2026-01-24T10:00:00Z"
},
"plain_key" : "pk_live_abc123def456ghi789jkl012mno345pqr678stu901vwx234yz"
},
"message" : "⚠️ Save this API key! It won't be shown again."
}
Save Your API Key: The plain_key is only shown once. Store it securely in environment variables or a secrets manager. You cannot retrieve it later.
List Merchant API Keys
/merchants/api-keys/merchant/:merchant_id
List all API keys for a merchant (without revealing actual key values).
Path Parameters
Required Permission: Owner
Example Request
curl -X GET https://paymentgateway.redahaloubi.com/api/v1/merchants/api-keys/merchant/{merchant_id} \
-H "Authorization: Bearer {access_token}"
Response (200 OK)
{
"success" : true ,
"data" : {
"api_keys" : [
{
"id" : "apikey_abc123" ,
"name" : "Production API Key" ,
"key_prefix" : "pk_live_" ,
"is_active" : true ,
"last_used_at" : "2026-01-25T15:30:00Z" ,
"created_at" : "2026-01-24T10:00:00Z"
},
{
"id" : "apikey_def456" ,
"name" : "Staging API Key" ,
"key_prefix" : "pk_test_" ,
"is_active" : true ,
"last_used_at" : "2026-01-25T12:00:00Z" ,
"created_at" : "2026-01-20T14:00:00Z"
}
]
}
}
Deactivate API Key
/merchants/api-keys/:merchant_id/:id/deactivate
Deactivate an API key without deleting it. Deactivated keys cannot be used but remain visible.
Path Parameters
Required Permission: Owner
Example Request
curl -X PATCH https://paymentgateway.redahaloubi.com/api/v1/merchants/api-keys/{merchant_id}/{api_key_id}/deactivate \
-H "Authorization: Bearer {access_token}"
Response (200 OK)
{
"success" : true ,
"message" : "API key deactivated successfully"
}
Delete API Key
/merchants/api-keys/:merchant_id/:id
Permanently delete an API key. This action cannot be undone.
Path Parameters
Required Permission: Owner
Example Request
curl -X DELETE https://paymentgateway.redahaloubi.com/api/v1/merchants/api-keys/{merchant_id}/{api_key_id} \
-H "Authorization: Bearer {access_token}"
Response (200 OK)
{
"success" : true ,
"message" : "API key deleted successfully"
}
Permanent Action: Deleted API keys cannot be recovered. Any services using this key will immediately stop working.
Permission Requirements Summary
Read Operations (All Roles)
Endpoints:
GET /merchants/:id
GET /merchants/:id/details
GET /merchants/:id/team
GET /merchants/:id/invitations
GET /merchants/:id/settings
Who Can Access: Owner, Admin, Manager, Staff
Create Operations (Owner, Admin, Manager)
Endpoints:
POST /merchants/:id/team/invite
Who Can Access: Owner, Admin, ManagerRestrictions: Staff cannot invite team members
Update Operations (Owner, Admin)
Endpoints:
PATCH /merchants/:id
PATCH /merchants/:id/settings
PATCH /merchants/:id/team/:user_id
Who Can Access: Owner, AdminRestrictions: Manager and Staff cannot modify merchant or settings
Delete Operations (Owner Only)
Endpoints:
DELETE /merchants/:id
DELETE /merchants/:id/team/:user_id
POST /merchants/api-keys (Create requires Owner)
All API key operations
Who Can Access: Owner onlyRestrictions: Even Admins cannot delete merchants or manage API keys
Common Workflows
Workflow 1: Setting Up a New Merchant
Create Merchant Account
User becomes Owner with full permissions
Configure Settings
PATCH /merchants/:id/settings
Set currency, webhooks, and preferences
Generate API Key
Create key for payment processing
Invite Team Members
POST /merchants/:id/team/invite
Add team members with appropriate roles
Workflow 2: Managing Team Members
Send Invitation
POST /merchants/:id/team/invite
Invitee receives email with token
User Accepts Invitation
POST /invitations/:token/accept
User joins merchant with assigned role
Update Role (if needed)
PATCH /merchants/:id/team/:user_id
Change team member’s role
Remove Member (if needed)
DELETE /merchants/:id/team/:user_id
Remove team member from merchant
Error Reference
Invalid request format or validation errors Common causes:
Invalid UUID format
Missing required fields
Invalid email format
Invalid business_type value
Missing or invalid authentication token Solution: Include valid JWT token in Authorization header
Authenticated but lacks required permissions Common causes:
Insufficient role permissions
Not a member of the merchant
Trying to perform owner-only actions
Requested resource doesn’t exist Common causes:
Invalid merchant ID
User not found
Invitation doesn’t exist
Request conflicts with current state Common causes:
User already has a merchant
Email already invited
User already in team
Next Steps
Questions? Contact support at [email protected]