Back to skills
SkillHub ClubShip Full StackFull Stack
mayar-payment-skill
Imported from https://github.com/openclaw/skills.
Packaged view
This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.
Stars
3,077
Hot score
99
Updated
March 20, 2026
Overall rating
C4.0
Composite score
4.0
Best-practice grade
F19.6
Install command
npx @skill-hub/cli install openclaw-skills-mayar-payment-skill
Repository
openclaw/skills
Skill path: skills/ahsanatha/mayar-payment-skill
Imported from https://github.com/openclaw/skills.
Open repositoryBest for
Primary workflow: Ship Full Stack.
Technical facets: Full Stack.
Target audience: everyone.
License: Unknown.
Original source
Catalog source: SkillHub Club.
Repository owner: openclaw.
This is still a mirrored public skill entry. Review the repository before installing into production workflows.
What it helps with
- Install mayar-payment-skill into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
- Review https://github.com/openclaw/skills before adding mayar-payment-skill to shared team environments
- Use mayar-payment-skill for development workflows
Works across
Claude CodeCodex CLIGemini CLIOpenCode
Favorites: 0.
Sub-skills: 0.
Aggregator: No.
Original source / Raw SKILL.md
---
name: mayar-payment
description: Mayar.id payment integration for generating invoices, payment links, and tracking transactions via MCP. Use when needing to: (1) Create payment invoices/links for customers, (2) Track payment status and transactions, (3) Generate WhatsApp-friendly payment messages, (4) Handle Indonesian payment methods (bank transfer, e-wallet, QRIS), (5) Manage subscriptions/memberships, or (6) Automate payment workflows for e-commerce, services, or digital products.
---
# Mayar Payment Integration
Integrate Mayar.id payment platform via MCP (Model Context Protocol) for Indonesian payment processing.
## Prerequisites
1. **Mayar.id account** - Sign up at https://mayar.id
2. **API Key** - Generate from https://web.mayar.id/api-keys
3. **mcporter configured** - MCP must be set up in Clawdbot
## Setup
### 1. Store API Credentials
```bash
mkdir -p ~/.config/mayar
cat > ~/.config/mayar/credentials << EOF
MAYAR_API_TOKEN="your-jwt-token-here"
EOF
chmod 600 ~/.config/mayar/credentials
```
### 2. Configure MCP Server
Add to `config/mcporter.json`:
```json
{
"mcpServers": {
"mayar": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://mcp.mayar.id/sse",
"--header",
"Authorization:YOUR_API_TOKEN_HERE"
]
}
}
}
```
Replace `YOUR_API_TOKEN_HERE` with actual token.
### 3. Test Connection
```bash
mcporter list mayar
```
Should show 15+ available tools.
## Core Workflows
### Create Invoice with Payment Link
**Most common use case:** Generate payment link for customer.
```bash
mcporter call mayar.create_invoice \
name="Customer Name" \
email="[email protected]" \
mobile="\"628xxx\"" \
description="Order description" \
redirectURL="https://yoursite.com/thanks" \
expiredAt="2026-12-31T23:59:59+07:00" \
items='[{"quantity":1,"rate":500000,"description":"Product A"}]'
```
**Returns:**
```json
{
"id": "uuid",
"transactionId": "uuid",
"link": "https://subdomain.myr.id/invoices/slug",
"expiredAt": 1234567890
}
```
**Key fields:**
- `mobile` - MUST be string with quotes: `"\"628xxx\""`
- `expiredAt` - ISO 8601 format with timezone
- `items` - Array of `{quantity, rate, description}`
- `redirectURL` - Where customer goes after payment
### WhatsApp Integration Pattern
```javascript
// 1. Create invoice
const invoice = /* mcporter call mayar.create_invoice */;
// 2. Format message
const message = `
ā
*Order Confirmed!*
*Items:*
⢠Product Name
Rp ${amount.toLocaleString('id-ID')}
*TOTAL: Rp ${total.toLocaleString('id-ID')}*
š³ *Pembayaran:*
${invoice.data.link}
ā° Berlaku sampai: ${expiryDate}
Terima kasih! š
`.trim();
// 3. Send via WhatsApp
message({
action: 'send',
channel: 'whatsapp',
target: customerPhone,
message: message
});
```
### Check Payment Status
```bash
# Get latest transactions (check if paid)
mcporter call mayar.get_latest_transactions page:1 pageSize:10
# Get unpaid invoices
mcporter call mayar.get_latest_unpaid_transactions page:1 pageSize:10
```
Filter by status: `"created"` (unpaid) ā `"paid"` (success).
### Other Operations
```bash
# Check account balance
mcporter call mayar.get_balance
# Get customer details
mcporter call mayar.get_customer_detail \
customerName="Name" \
customerEmail="[email protected]" \
page:1 pageSize:10
# Filter by time period
mcporter call mayar.get_transactions_by_time_period \
page:1 pageSize:10 \
period:"this_month" \
sortField:"createdAt" \
sortOrder:"DESC"
```
## Common Patterns
### Multi-Item Invoice
```javascript
items='[
{"quantity":2,"rate":500000,"description":"Product A"},
{"quantity":1,"rate":1000000,"description":"Product B"}
]'
// Total: 2M (2Ć500K + 1Ć1M)
```
### Subscription/Recurring
Use membership tools:
```bash
mcporter call mayar.get_membership_customer_by_specific_product \
productName:"Premium Membership" \
productLink:"your-product-link" \
productId:"product-uuid" \
page:1 pageSize:10 \
memberStatus:"active"
```
### Payment Confirmation Flow
**Option A: Webhook** (Real-time)
- Register webhook URL with Mayar
- Receive instant payment notifications
- Best for production
**Option B: Polling** (Simpler)
- Poll `get_latest_transactions` every 30-60s
- Check for new payments
- Best for MVP/testing
## Troubleshooting
**404 on payment link:**
- Link format: `https://your-subdomain.myr.id/invoices/slug`
- Check dashboard for correct subdomain
- Default may be account name
**Invalid mobile number:**
- Mobile MUST be string: `"\"628xxx\""` (with escaped quotes)
- Format: `628xxxxxxxxxx` (no + or spaces)
**Expired invoice:**
- Default expiry is `expiredAt` timestamp
- Customer can't pay after expiration
- Create new invoice if needed
## Reference Documentation
- **API Details:** See [references/api-reference.md](references/api-reference.md)
- **Integration Examples:** See [references/integration-examples.md](references/integration-examples.md)
- **MCP Tools Reference:** See [references/mcp-tools.md](references/mcp-tools.md)
## Production Checklist
- [ ] Use production API key (not sandbox)
- [ ] Setup webhook for payment notifications
- [ ] Error handling for failed invoice creation
- [ ] Store invoice IDs for tracking
- [ ] Handle payment expiration
- [ ] Customer database integration
- [ ] Receipt/confirmation automation
## Environments
**Production:**
- Dashboard: https://web.mayar.id
- API Base: `https://api.mayar.id/hl/v1/`
**Sandbox (Testing):**
- Dashboard: https://web.mayar.club
- API Base: `https://api.mayar.club/hl/v1/`
---
## Referenced Files
> The following files are referenced in this skill and included for context.
### references/api-reference.md
```markdown
# Mayar.id API Reference
## Overview
Mayar.id provides a headless e-commerce API for Indonesian payment processing. This reference covers the REST API endpoints (alternative to MCP).
**Official Documentation:** https://docs.mayar.id/api-reference/introduction
## Authentication
All API requests require Bearer token authentication.
```bash
Authorization: Bearer YOUR_JWT_TOKEN
```
Get your API key from:
- **Production:** https://web.mayar.id/api-keys
- **Sandbox:** https://web.mayar.club/api-keys
## Base URLs
**Production:**
```
https://api.mayar.id/hl/v1/
```
**Sandbox (Testing):**
```
https://api.mayar.club/hl/v1/
```
## Core Endpoints
### Invoice
#### Create Invoice (POST)
```
POST /hl/v1/invoice/create
```
**Request Body:**
```json
{
"name": "Customer Name",
"email": "[email protected]",
"mobile": "6281234567890",
"description": "Order description",
"redirectURL": "https://yoursite.com/success",
"expiredAt": "2026-12-31T23:59:59+07:00",
"items": [
{
"quantity": 1,
"rate": 500000,
"description": "Product A"
}
]
}
```
**Response:**
```json
{
"statusCode": 200,
"messages": "success",
"data": {
"id": "uuid",
"transactionId": "uuid",
"link": "https://subdomain.myr.id/invoices/slug",
"expiredAt": 1234567890123
}
}
```
#### Get Invoice List (GET)
```
GET /hl/v1/invoice
```
**Query Parameters:**
- `page` - Page number
- `pageSize` - Items per page
#### Get Invoice Detail (GET)
```
GET /hl/v1/invoice/:invoiceId
```
#### Edit Invoice (POST)
```
POST /hl/v1/invoice/edit
```
#### Close Invoice (GET)
```
GET /hl/v1/invoice/:invoiceId/close
```
#### Reopen Invoice (GET)
```
GET /hl/v1/invoice/:invoiceId/reopen
```
### Request Payment
#### Create Single Payment Request (POST)
```
POST /hl/v1/request-payment/create
```
**Request Body:**
```json
{
"name": "Customer Name",
"email": "[email protected]",
"mobile": "6281234567890",
"amount": 500000,
"description": "Simple payment",
"redirectURL": "https://yoursite.com/success",
"expiredAt": "2026-12-31T23:59:59+07:00"
}
```
**Difference from Invoice:**
- `amount` instead of `items[]`
- Simpler for single-amount payments
- No itemization
### Product
#### Get Product Page (GET)
```
GET /hl/v1/product/page
```
#### Search Product (GET)
```
GET /hl/v1/product/search?q=keyword
```
#### Get Product Detail (GET)
```
GET /hl/v1/product/:productId
```
### Customer
#### Get Customer (GET)
```
GET /hl/v1/customer/:customerId
```
#### Create Customer (POST)
```
POST /hl/v1/customer/create
```
**Request Body:**
```json
{
"name": "Customer Name",
"email": "[email protected]",
"mobile": "6281234567890"
}
```
#### Update Customer Email (POST)
```
POST /hl/v1/customer/update-email
```
#### Create Magic Link (POST)
```
POST /hl/v1/customer/magic-link
```
Generates passwordless login link for customer portal.
### Webhook
#### Register URL Hook (POST)
```
POST /hl/v1/webhook/register
```
**Request Body:**
```json
{
"urlHook": "https://yoursite.com/webhook"
}
```
**Response:**
```json
{
"statusCode": 200,
"messages": "success"
}
```
#### Test URL Hook (POST)
```
POST /hl/v1/webhook/test
```
Sends test webhook to registered URL.
#### Get Webhook History (GET)
```
GET /hl/v1/webhook/history
```
#### Retry Webhook (POST)
```
POST /hl/v1/webhook/retry
```
## Webhook Payload
When payment is successful, Mayar sends POST request to your registered webhook URL:
```json
{
"eventType": "transaction.paid",
"data": {
"id": "transaction-uuid",
"invoiceId": "invoice-uuid",
"customerId": "customer-uuid",
"amount": 500000,
"status": "paid",
"paymentMethod": "bank_transfer",
"paidAt": "2026-01-31T12:34:56+07:00",
"customer": {
"name": "Customer Name",
"email": "[email protected]",
"mobile": "6281234567890"
}
}
}
```
**Event Types:**
- `transaction.paid` - Payment successful
- `transaction.failed` - Payment failed
- `transaction.expired` - Invoice expired
- `transaction.refunded` - Payment refunded
## Payment Methods
Mayar supports various Indonesian payment methods:
**Bank Transfer:**
- BCA
- Mandiri
- BNI
- BRI
- Permata
- CIMB Niaga
**E-Wallet:**
- GoPay
- OVO
- DANA
- LinkAja
- ShopeePay
**Others:**
- QRIS (QR Code)
- Virtual Account
- Credit/Debit Card (via partner)
## Data Formats
### Phone Numbers
- Format: `"628xxxxxxxxxx"`
- No + symbol
- No spaces or dashes
- Country code 62 (Indonesia)
### Dates (ISO 8601)
```
2026-12-31T23:59:59+07:00
```
- Include timezone (+07:00 for Jakarta)
- YYYY-MM-DDTHH:mm:ss+TZ
### Currency
- Integer (no decimals)
- In Rupiah
- Example: `500000` = Rp 500,000
### Status Values
**Invoice:**
- `created` - Unpaid
- `paid` - Payment successful
- `expired` - Past expiration date
- `cancelled` - Manually cancelled
**Transaction:**
- `pending` - Awaiting payment
- `processing` - Payment being verified
- `paid` - Payment confirmed
- `failed` - Payment failed
- `refunded` - Payment refunded
**Membership:**
- `active` - Currently active
- `inactive` - Not active
- `finished` - Completed
- `stopped` - Manually stopped
## Rate Limits
Mayar does not publicly document rate limits, but recommended practice:
- Max 10 requests/second per endpoint
- Use exponential backoff for retries
- Cache responses when possible
## Error Codes
```json
{
"statusCode": 400,
"messages": "Invalid request",
"errors": [
{
"field": "email",
"message": "Invalid email format"
}
]
}
```
**Common Status Codes:**
- `200` - Success
- `400` - Bad Request (validation error)
- `401` - Unauthorized (invalid API key)
- `404` - Not Found
- `422` - Unprocessable Entity (business logic error)
- `500` - Internal Server Error
## Pagination
Most list endpoints support pagination:
**Query Parameters:**
- `page` - Page number (starts from 1)
- `pageSize` - Items per page (default: 10, max: 100)
**Response:**
```json
{
"currentPage": 1,
"totalPage": 5,
"pageSize": 10,
"totalData": 47,
"nextPage": 2,
"previousPage": null,
"data": [...]
}
```
## Filtering & Sorting
**Time-based filtering:**
- `period` - `today`, `this_week`, `this_month`, `this_year`
- `startAt` / `endAt` - Custom date range (ISO 8601)
**Sorting:**
- `sortField` - Field to sort by (`createdAt`, `amount`)
- `sortOrder` - `ASC` or `DESC`
## Best Practices
### 1. Use Idempotency
Store invoice IDs to avoid duplicate invoice creation:
```javascript
const existingInvoice = cache.get(orderId);
if (existingInvoice) {
return existingInvoice;
}
const newInvoice = await createInvoice(...);
cache.set(orderId, newInvoice);
```
### 2. Handle Webhooks Properly
```javascript
app.post('/webhook', (req, res) => {
// Respond immediately
res.status(200).json({ received: true });
// Process async
processPayment(req.body).catch(console.error);
});
```
### 3. Validate Webhook Signature
(If Mayar provides signature verification - check docs)
### 4. Set Appropriate Expiry
```javascript
// Short for immediate purchase (24h)
const expiry = new Date(Date.now() + 24 * 60 * 60 * 1000);
// Longer for invoices (7-30 days)
const expiry = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
```
### 5. Store Transaction Data
```javascript
{
orderId: "ORD-123",
invoiceId: "mayar-invoice-uuid",
transactionId: "mayar-transaction-uuid",
customerId: "customer-uuid",
amount: 500000,
status: "pending",
createdAt: "2026-01-31T12:00:00Z",
paidAt: null
}
```
## Sandbox vs Production
**Sandbox:**
- Use for testing
- No real payments
- Separate dashboard (web.mayar.club)
- Separate API keys
**Production:**
- Real payments
- Live dashboard (web.mayar.id)
- Production API keys
- Use after thorough testing
**Migration:**
- Generate new API key from production
- Update base URL
- Test with small amount first
## Support
- **Community:** https://t.me/mcngroup
- **Blog:** https://blog.mayar.id
- **Dashboard:** https://web.mayar.id
For technical issues, contact via dashboard support.
```
### references/integration-examples.md
```markdown
# Mayar Integration Examples
Real-world integration patterns for common use cases.
## WhatsApp E-Commerce Bot
### Complete Order Flow
```javascript
// 1. Customer sends order via WhatsApp
// "Mau order wedding template + maintenance 2 bulan"
// 2. Parse order and create invoice
const items = [
{ quantity: 1, rate: 750000, description: "Wedding Website Template" },
{ quantity: 2, rate: 1000000, description: "Monthly Maintenance" }
];
const total = items.reduce((sum, item) => sum + (item.quantity * item.rate), 0);
// Total: 2,750,000
// 3. Create invoice via mcporter
const invoice = execSync(`
mcporter call mayar.create_invoice \\
name="Customer Name" \\
email="[email protected]" \\
mobile="\\"6281234567890\\"" \\
description="Wedding Template + Maintenance Package" \\
redirectURL="https://yoursite.com/success" \\
expiredAt="2026-02-07T23:59:59+07:00" \\
items='${JSON.stringify(items)}' \\
--output json
`);
const result = JSON.parse(invoice);
const paymentLink = result.data.link.replace('tsrlabs', 'yoursubdomain');
// 4. Format WhatsApp message
const message = `
ā
*Order Confirmed!*
*Package:* Wedding Template + Maintenance
*Items:*
⢠Wedding Website Template
Rp 750.000
⢠Monthly Maintenance x2
Rp 2.000.000
*TOTAL: Rp 2.750.000*
š³ *Pembayaran:*
${paymentLink}
ā° Berlaku sampai: 7 Feb 2026
Terima kasih! š
`.trim();
// 5. Send via WhatsApp
message({
action: 'send',
channel: 'whatsapp',
target: '+6281234567890',
message: message
});
```
### Payment Status Polling
```javascript
// Poll every 30 seconds to check payment status
setInterval(async () => {
const transactions = execSync(`
mcporter call mayar.get_latest_transactions page:1 pageSize:10 --output json
`);
const data = JSON.parse(transactions);
// Check if our invoice ID exists in paid transactions
const paid = data.data.find(t =>
t.paymentLinkId === invoiceId && t.status === 'paid'
);
if (paid) {
// Send confirmation
message({
action: 'send',
channel: 'whatsapp',
target: customerPhone,
message: `
ā
*Pembayaran Berhasil!*
Invoice: #${paid.invoiceCode}
Amount: Rp ${paid.amount.toLocaleString('id-ID')}
Tanggal: ${paid.createdAt}
Setup akan segera dimulai. Terima kasih! š
`.trim()
});
clearInterval(this); // Stop polling
}
}, 30000); // Every 30 seconds
```
## Service Marketplace
### Multi-Service Package
```bash
# Customer orders multiple services
mcporter call mayar.create_invoice \
name="Business Client" \
email="[email protected]" \
mobile="\"6281234567890\"" \
description="Digital Services Package" \
redirectURL="https://yoursite.com/success" \
expiredAt="2026-02-28T23:59:59+07:00" \
items='[
{"quantity":1,"rate":5000000,"description":"WhatsApp Bot Setup + CRM"},
{"quantity":1,"rate":3000000,"description":"Website Development"},
{"quantity":3,"rate":1000000,"description":"Monthly Maintenance"}
]'
```
Total: Rp 11,000,000 (5M + 3M + 3M)
### Recurring Billing Reminder
```javascript
// Check unpaid invoices and send reminders
const unpaid = execSync(`
mcporter call mayar.get_latest_unpaid_transactions page:1 pageSize:50 --output json
`);
const overdue = JSON.parse(unpaid).data.filter(t => {
const expiry = new Date(t.paymentLink.expiredAt);
const soon = Date.now() + (24 * 60 * 60 * 1000); // 24 hours
return expiry.getTime() < soon && expiry.getTime() > Date.now();
});
// Send reminder for each overdue invoice
overdue.forEach(invoice => {
message({
action: 'send',
channel: 'whatsapp',
target: invoice.customer.mobile,
message: `
ā° *Reminder: Pembayaran akan segera kadaluarsa*
Invoice: #${invoice.invoiceCode}
Amount: Rp ${invoice.amount.toLocaleString('id-ID')}
Kadaluarsa: ${new Date(invoice.paymentLink.expiredAt).toLocaleString('id-ID')}
Link pembayaran:
${invoice.paymentLink.link}
Terima kasih! š
`.trim()
});
});
```
## Membership Site
### Check Active Members
```bash
mcporter call mayar.get_membership_customer_by_specific_product \
productName:"Premium Membership" \
productLink:"premium-membership" \
productId:"your-product-uuid" \
page:1 pageSize:100 \
memberStatus:"active"
```
### Membership Renewal Automation
```javascript
// Get members expiring soon
const members = execSync(`
mcporter call mayar.get_membership_customer_by_specific_product \
productName:"Premium Membership" \
productLink:"premium-membership" \
productId:"uuid" \
page:1 pageSize:100 \
memberStatus:"active" \
--output json
`);
const expiringSoon = JSON.parse(members).data.filter(member => {
const expiry = new Date(member.expirationDate);
const week = Date.now() + (7 * 24 * 60 * 60 * 1000);
return expiry.getTime() < week;
});
// Create renewal invoice for each
expiringSoon.forEach(member => {
const renewalInvoice = createInvoice({
name: member.customerName,
email: member.customerEmail,
mobile: member.customerMobile,
description: "Premium Membership Renewal",
items: [
{ quantity: 1, rate: 500000, description: "Premium Membership - 1 Month" }
]
});
// Send renewal notification via email/WhatsApp
});
```
## Course/Digital Product Sales
### Course Purchase with Auto-Access
```javascript
// 1. Create invoice for course
const invoice = createInvoice({
name: "Student Name",
email: "[email protected]",
mobile: "6281234567890",
description: "Full Stack Development Course",
items: [
{ quantity: 1, rate: 2500000, description: "Full Stack Dev Course" }
]
});
// 2. Monitor payment
pollPayment(invoice.data.id, async (paidInvoice) => {
// 3. Grant course access
await grantCourseAccess(paidInvoice.customer.email);
// 4. Send access credentials
message({
action: 'send',
channel: 'whatsapp',
target: paidInvoice.customer.mobile,
message: `
š *Pembayaran Berhasil!*
Kamu sekarang memiliki akses ke:
š Full Stack Development Course
Login di: https://course.site/login
Email: ${paidInvoice.customer.email}
Password: (cek email)
Selamat belajar! š
`.trim()
});
});
```
## Donation Platform
### One-Time Donation
```bash
mcporter call mayar.create_invoice \
name="Donor Name" \
email="[email protected]" \
mobile="\"6281234567890\"" \
description="Donation for Education Program" \
redirectURL="https://donation-site.com/thanks" \
expiredAt="2026-12-31T23:59:59+07:00" \
items='[{"quantity":1,"rate":100000,"description":"Education Fund Donation"}]'
```
### Donation with Custom Amount
```javascript
function createDonationInvoice(donorInfo, amount, program) {
return createInvoice({
name: donorInfo.name,
email: donorInfo.email,
mobile: donorInfo.phone,
description: `Donation for ${program}`,
items: [
{ quantity: 1, rate: amount, description: `${program} - Donation` }
]
});
}
// Usage
const donation = createDonationInvoice(
{ name: "John Doe", email: "[email protected]", phone: "6281234567890" },
500000,
"Clean Water Project"
);
```
## Event Ticketing
### Multiple Ticket Types
```bash
mcporter call mayar.create_invoice \
name="Attendee Name" \
email="[email protected]" \
mobile="\"6281234567890\"" \
description="Tech Conference 2026 Tickets" \
redirectURL="https://event-site.com/tickets" \
expiredAt="2026-03-01T23:59:59+07:00" \
items='[
{"quantity":2,"rate":500000,"description":"Early Bird Ticket"},
{"quantity":1,"rate":150000,"description":"Workshop Add-on"}
]'
```
Total: Rp 1,150,000 (2Ć500K + 1Ć150K)
### Post-Payment Ticket Delivery
```javascript
pollPayment(invoiceId, async (paidInvoice) => {
// Generate QR code tickets
const tickets = await generateTickets(paidInvoice);
// Send tickets via WhatsApp
tickets.forEach((ticket, index) => {
message({
action: 'send',
channel: 'whatsapp',
target: paidInvoice.customer.mobile,
message: `
šļø *Ticket ${index + 1}*
Event: Tech Conference 2026
Date: 15 March 2026
Venue: JCC Hall A
Scan QR code at entrance:
${ticket.qrCodeUrl}
See you there! š
`.trim()
});
});
});
```
## Analytics & Reporting
### Daily Revenue Report
```javascript
const today = execSync(`
mcporter call mayar.get_transactions_by_time_period \
page:1 pageSize:100 \
period:"today" \
sortField:"createdAt" \
sortOrder:"DESC" \
--output json
`);
const transactions = JSON.parse(today).data;
const revenue = transactions.reduce((sum, t) => sum + t.amount, 0);
const count = transactions.length;
const report = `
š *Daily Revenue Report*
Date: ${new Date().toLocaleDateString('id-ID')}
š° Total Revenue: Rp ${revenue.toLocaleString('id-ID')}
š¦ Transactions: ${count}
šµ Average: Rp ${Math.round(revenue / count).toLocaleString('id-ID')}
Top 5 Sales:
${transactions.slice(0, 5).map(t =>
`⢠${t.paymentLinkDescription}: Rp ${t.amount.toLocaleString('id-ID')}`
).join('\n')}
`.trim();
// Send to admin
message({
action: 'send',
channel: 'whatsapp',
target: '+628xxxx', // Admin number
message: report
});
```
### Monthly Summary
```bash
mcporter call mayar.get_transactions_by_time_period \
page:1 pageSize:1000 \
period:"this_month" \
sortField:"amount" \
sortOrder:"DESC"
```
## Error Handling
### Retry Failed Invoices
```javascript
function createInvoiceWithRetry(data, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const invoice = execSync(`
mcporter call mayar.create_invoice \
name="${data.name}" \
email="${data.email}" \
mobile="\\"${data.mobile}\\"" \
description="${data.description}" \
redirectURL="${data.redirectURL}" \
expiredAt="${data.expiredAt}" \
items='${JSON.stringify(data.items)}' \
--output json
`);
return JSON.parse(invoice);
} catch (error) {
console.error(`Attempt ${i + 1} failed:`, error.message);
if (i === maxRetries - 1) throw error;
// Wait before retry (exponential backoff)
await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, i)));
}
}
}
```
### Handle Expired Invoices
```javascript
function recreateExpiredInvoice(oldInvoiceId) {
// Get old invoice details
const unpaid = execSync(`
mcporter call mayar.get_latest_unpaid_transactions page:1 pageSize:100 --output json
`);
const oldInvoice = JSON.parse(unpaid).data.find(t => t.id === oldInvoiceId);
if (!oldInvoice) {
throw new Error('Invoice not found');
}
// Create new invoice with same details but new expiry
const newExpiry = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString();
return createInvoice({
name: oldInvoice.paymentLinkName,
email: oldInvoice.customer.email,
mobile: oldInvoice.customer.mobile,
description: oldInvoice.paymentLinkDescription,
expiredAt: newExpiry,
items: oldInvoice.items // Extract from original
});
}
```
## Best Practices
### 1. Always Store Invoice IDs
```javascript
// Store mapping: customer ā invoice ID
const invoiceDB = {
[customerPhone]: {
invoiceId: result.data.id,
transactionId: result.data.transactionId,
createdAt: Date.now(),
status: 'pending'
}
};
```
### 2. Set Reasonable Expiry Times
```javascript
// For immediate purchases: 24 hours
const expiry24h = new Date(Date.now() + 24 * 60 * 60 * 1000);
// For orders: 7 days
const expiry7d = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
// For invoices: 30 days
const expiry30d = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000);
```
### 3. Format Phone Numbers Correctly
```javascript
function formatPhoneForMayar(phone) {
// Remove all non-digits
let cleaned = phone.replace(/\D/g, '');
// Add country code if missing
if (!cleaned.startsWith('62')) {
cleaned = '62' + cleaned.replace(/^0+/, '');
}
return cleaned;
}
```
### 4. Handle Timezone Correctly
```javascript
// Always use Jakarta timezone for Indonesian customers
const expiry = new Date();
expiry.setDate(expiry.getDate() + 7);
const expiryISO = expiry.toISOString().replace('Z', '+07:00');
```
```
### references/mcp-tools.md
```markdown
# Mayar MCP Tools Reference
Complete list of available tools via Mayar MCP server.
## Payment Generation
### create_invoice
Create itemized invoice with payment link.
**Input:**
- `name` (string, required) - Customer name
- `email` (string, required) - Customer email
- `mobile` (string, required) - Customer phone (format: "628xxx")
- `description` (string, required) - Order description
- `redirectURL` (string, required) - Post-payment redirect URL
- `expiredAt` (string, required) - Expiry date (ISO 8601 with timezone)
- `items` (array, required) - Items array:
- `quantity` (number) - Item quantity
- `rate` (number) - Price per unit (in Rupiah)
- `description` (string) - Item name
**Output:**
- `id` - Invoice UUID
- `transactionId` - Transaction UUID
- `link` - Payment link URL
- `expiredAt` - Expiry timestamp (epoch ms)
**Example:**
```bash
mcporter call mayar.create_invoice \
name="John Doe" \
email="[email protected]" \
mobile="\"6281234567890\"" \
description="Product purchase" \
redirectURL="https://example.com/thanks" \
expiredAt="2026-12-31T23:59:59+07:00" \
items='[{"quantity":1,"rate":100000,"description":"Product A"}]'
```
### send_portal_link
Send customer portal access link via email.
**Input:**
- `email` (string, required) - Customer email
**Output:**
- Success status
## Balance & Account
### get_balance
Get current account balance.
**Input:** None
**Output:**
- `balanceActive` - Available balance
- `balancePending` - Pending balance
- `balance` - Total balance
**Example:**
```bash
mcporter call mayar.get_balance
```
## Transaction Queries
### get_latest_transactions
Get recent paid transactions.
**Input:**
- `page` (number, required) - Page number (start from 1)
- `pageSize` (number, required) - Items per page
**Output:**
- `currentPage`, `totalPage`, `totalData`
- `data` - Array of transactions
### get_latest_unpaid_transactions
Get unpaid invoices.
**Input:**
- `page` (number, required)
- `pageSize` (number, required)
**Output:**
- Array of unpaid transactions
### get_transactions_by_time_period
Filter transactions by predefined periods.
**Input:**
- `page` (number, required)
- `pageSize` (number, required)
- `period` (string, required) - One of: `"today"`, `"this_week"`, `"this_month"`, `"this_year"`
- `sortField` (string, required) - `"createdAt"` or `"amount"`
- `sortOrder` (string, required) - `"ASC"` or `"DESC"`
**Example:**
```bash
mcporter call mayar.get_transactions_by_time_period \
page:1 pageSize:10 \
period:"this_month" \
sortField:"createdAt" \
sortOrder:"DESC"
```
### get_transactions_by_time_range
Filter transactions by custom date range.
**Input:**
- `page`, `pageSize` (numbers, required)
- `startAt` (string, required) - Start date (ISO 8601)
- `endAt` (string, required) - End date (ISO 8601)
- `sortField`, `sortOrder` (strings, required)
**Example:**
```bash
mcporter call mayar.get_transactions_by_time_range \
page:1 pageSize:10 \
startAt:"2026-01-01T00:00:00+07:00" \
endAt:"2026-01-31T23:59:59+07:00" \
sortField:"amount" \
sortOrder:"DESC"
```
### get_transactions_by_customer_and_time_period
Filter by customer AND time period.
**Input:**
- `page`, `pageSize`, `period`, `sortField`, `sortOrder` (as above)
- `customerEmail` (string, required)
- `customerName` (string, required)
### get_transactions_by_customer_and_time_range
Filter by customer AND custom date range.
**Input:**
- `page`, `pageSize`, `startAt`, `endAt`, `sortField`, `sortOrder` (as above)
- `customerName`, `customerEmail` (strings, required)
### get_unpaid_transactions_by_time_range
Get unpaid transactions in date range.
**Input:**
- All fields from `get_transactions_by_time_range`
- Plus: `customerName`, `customerEmail` (strings, required)
## Customer Management
### get_customer_detail
Get customer transaction history.
**Input:**
- `customerName` (string, required)
- `customerEmail` (string, required)
- `page` (number, required)
- `pageSize` (number, required)
**Output:**
- Customer details + transaction list
## Product-Specific Queries
### get_transactions_by_specific_product
Get transactions for a specific product.
**Input:**
- `productName` (string, required)
- `productLink` (string, required)
- `productId` (string, required)
- `page`, `pageSize` (numbers, required)
### get_latest_transactions_by_customer
Filter by customer + product.
**Input:**
- `customerName`, `customerEmail` (strings, required)
- `productName`, `productLink` (strings, required)
- `page`, `pageSize` (numbers, required)
## Membership/Subscription Tools
### get_membership_customer_by_specific_product
Get membership customers for a product.
**Input:**
- `productName`, `productLink`, `productId` (strings, required)
- `page`, `pageSize` (numbers, required)
- `memberStatus` (string, required) - One of: `"active"`, `"inactive"`, `"finished"`, `"stopped"`
**Example:**
```bash
mcporter call mayar.get_membership_customer_by_specific_product \
productName:"Premium Membership" \
productLink:"premium-membership" \
productId:"uuid-here" \
page:1 pageSize:10 \
memberStatus:"active"
```
### get_membership_customer_by_specific_product_and_tier
Filter membership by tier.
**Input:**
- All fields from above
- Plus: `membershipTierName`, `membershipTierId` (strings, required)
## Common Patterns
### Check if Invoice is Paid
```bash
# Get unpaid transactions
result=$(mcporter call mayar.get_latest_unpaid_transactions page:1 pageSize:50 --output json)
# Check if your invoice ID exists
# If NOT in unpaid list ā it's paid!
```
### Get Today's Revenue
```bash
mcporter call mayar.get_transactions_by_time_period \
page:1 pageSize:100 \
period:"today" \
sortField:"amount" \
sortOrder:"DESC"
```
### Find Customer's Last Purchase
```bash
mcporter call mayar.get_customer_detail \
customerName:"Customer Name" \
customerEmail:"[email protected]" \
page:1 pageSize:1
```
## Field Formats
**Phone Numbers:**
- Format: `"628xxxxxxxxxx"` (no + or spaces)
- Must be string with escaped quotes in CLI: `"\"628xxx\""`
**Dates (ISO 8601):**
- With timezone: `"2026-12-31T23:59:59+07:00"`
- UTC: `"2026-12-31T23:59:59Z"`
**Currency:**
- Always in Rupiah (integer)
- No decimal points
- Example: `100000` = Rp 100,000
**Status Values:**
- Invoice: `"created"` (unpaid), `"paid"`, `"expired"`, `"cancelled"`
- Member: `"active"`, `"inactive"`, `"finished"`, `"stopped"`
**Time Periods:**
- `"today"`, `"this_week"`, `"this_month"`, `"this_year"`
**Sort Fields:**
- `"createdAt"`, `"amount"`
**Sort Order:**
- `"ASC"` (ascending), `"DESC"` (descending)
```
---
## Skill Companion Files
> Additional files collected from the skill directory layout.
### README.md
```markdown
# Mayar Payment Integration - Clawdbot Skill
[](https://opensource.org/licenses/MIT)
[](https://github.com/ahsanatha/mayar-payment-skill)
Complete Mayar.id payment integration for Clawdbot. Enable your AI agent to generate invoices, payment links, and track transactions via Indonesian payment platform.
## šÆ Features
- ā
Create payment invoices with itemized billing
- ā
Generate payment links for customers
- ā
Track transactions & payment status
- ā
Support ALL Indonesian payment methods (bank transfer, e-wallet, QRIS)
- ā
WhatsApp/Telegram/Discord payment workflows
- ā
Membership/subscription management
- ā
Complete MCP (Model Context Protocol) integration
- ā
15 ready-to-use MCP tools
## š Quick Start
### Prerequisites
- Clawdbot instance with mcporter installed
- Mayar.id account (free signup at [mayar.id](https://mayar.id))
- Node.js (for mcporter)
### Installation
**1. Clone this repository**
```bash
cd ~/.clawdbot/skills # or your Clawdbot skills directory
git clone https://github.com/ahsanatha/mayar-payment-skill.git mayar-payment
```
**2. Get Mayar API Key**
- Sign up at https://mayar.id
- Go to https://web.mayar.id/api-keys
- Generate new API key (JWT token)
**For testing, use sandbox:**
- Dashboard: https://web.mayar.club
- API Keys: https://web.mayar.club/api-keys
**3. Configure Credentials**
```bash
mkdir -p ~/.config/mayar
cat > ~/.config/mayar/credentials << EOF
MAYAR_API_TOKEN="your-jwt-token-here"
EOF
chmod 600 ~/.config/mayar/credentials
```
**4. Configure MCP Server**
Add to your `config/mcporter.json`:
```json
{
"mcpServers": {
"mayar": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://mcp.mayar.id/sse",
"--header",
"Authorization:YOUR_API_TOKEN_HERE"
]
}
}
}
```
Replace `YOUR_API_TOKEN_HERE` with your actual JWT token.
**5. Test Installation**
```bash
# List available tools
mcporter list mayar
# Test balance check
mcporter call mayar.get_balance
```
If you see 15 available tools ā Installation successful! ā
## š” Usage Examples
### Create Payment Invoice
```bash
mcporter call mayar.create_invoice \
name="Customer Name" \
email="[email protected]" \
mobile="\"628xxxxxxxxxx\"" \
description="Order description" \
redirectURL="https://yoursite.com/success" \
expiredAt="2026-12-31T23:59:59+07:00" \
items='[
{"quantity":1,"rate":500000,"description":"Product A"},
{"quantity":2,"rate":100000,"description":"Product B"}
]'
```
Returns payment link: `https://subdomain.myr.id/invoices/xxxxx`
### WhatsApp Integration
```javascript
// Create invoice
const invoice = /* mcporter call mayar.create_invoice ... */;
// Format message
const message = `
ā
*Order Confirmed!*
*Total: Rp ${total.toLocaleString('id-ID')}*
š³ Pembayaran:
${invoice.data.link}
ā° Berlaku sampai: ${expiryDate}
`.trim();
// Send via WhatsApp
message({
action: 'send',
channel: 'whatsapp',
target: customerPhone,
message: message
});
```
### Check Transactions
```bash
# Latest transactions
mcporter call mayar.get_latest_transactions page:1 pageSize:10
# Unpaid invoices
mcporter call mayar.get_latest_unpaid_transactions page:1 pageSize:10
# Today's revenue
mcporter call mayar.get_transactions_by_time_period \
page:1 pageSize:100 \
period:"today" \
sortField:"amount" \
sortOrder:"DESC"
```
## š Documentation
- **[SKILL.md](SKILL.md)** - Main skill guide with setup & workflows
- **[MCP Tools Reference](references/mcp-tools.md)** - Complete list of 15 MCP tools
- **[Integration Examples](references/integration-examples.md)** - Real-world patterns (WhatsApp bots, subscriptions, events, etc.)
- **[API Reference](references/api-reference.md)** - REST API documentation (alternative to MCP)
## šÆ Use Cases
- **E-commerce bots** - Automated order processing via WhatsApp/Telegram
- **Service marketplace** - Sell services with instant payment links
- **Course platforms** - Sell courses with auto-access after payment
- **Membership sites** - Subscription & tier management
- **Event ticketing** - Generate tickets after payment
- **Donation platforms** - Accept donations with tracking
- **Wedding services** - Sell templates/packages
- **Freelance payments** - Professional invoicing
## š§ Available MCP Tools
### Payment Generation
- `create_invoice` - Create itemized invoice with payment link
- `send_portal_link` - Send customer portal access
- `get_balance` - Check account balance
### Transaction Queries
- `get_latest_transactions` - Recent paid transactions
- `get_latest_unpaid_transactions` - Pending payments
- `get_customer_detail` - Customer transaction history
- `get_transactions_by_time_period` - Filter by period
- `get_transactions_by_time_range` - Custom date range
- Plus 7 more filtering/query tools...
### Membership Management
- `get_membership_customer_by_specific_product`
- `get_membership_customer_by_specific_product_and_tier`
[See full tool reference ā](references/mcp-tools.md)
## š Payment Methods Supported
Mayar.id supports all major Indonesian payment methods:
**Bank Transfer:** BCA, Mandiri, BNI, BRI, Permata, CIMB Niaga
**E-Wallet:** GoPay, OVO, DANA, LinkAja, ShopeePay
**Others:** QRIS, Virtual Account, Credit/Debit Card
## š ļø Troubleshooting
### "MCP server not found"
```bash
mcporter config list
mcporter list mayar
```
### "Invalid mobile number"
Phone must be:
- String format: `"\"628xxx\""`
- No + symbol, no spaces
- Country code 62 (Indonesia)
### "404 on payment link"
Check your Mayar subdomain in dashboard settings.
Link format: `https://subdomain.myr.id/invoices/slug`
### "Webhook not working"
1. Register webhook URL:
```bash
curl -X POST https://api.mayar.id/hl/v1/webhook/register \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"urlHook":"https://yoursite.com/webhook"}'
```
2. Ensure URL is publicly accessible
3. Must respond with 200 status
## š Skill Architecture
```
mayar-payment/
āāā SKILL.md # Main skill documentation
āāā README.md # This file (GitHub)
āāā references/
āāā api-reference.md # REST API docs (8KB)
āāā mcp-tools.md # MCP tools reference (6.6KB)
āāā integration-examples.md # Real-world patterns (12KB)
```
Following Clawdbot skill best practices:
- Progressive disclosure (main guide ā detailed references)
- Concise core documentation
- Real-world examples
- Production-ready patterns
## š Environments
**Production:**
- Dashboard: https://web.mayar.id
- API: `https://api.mayar.id/hl/v1/`
**Sandbox (Testing):**
- Dashboard: https://web.mayar.club
- API: `https://api.mayar.club/hl/v1/`
Always test in sandbox first before using production!
## š¤ Contributing
Contributions welcome! Please:
1. Fork the repository
2. Create feature branch (`git checkout -b feature/amazing`)
3. Commit changes (`git commit -m 'Add amazing feature'`)
4. Push to branch (`git push origin feature/amazing`)
5. Open Pull Request
## š License
MIT License - Free to use, modify, and distribute.
See [LICENSE](LICENSE) file for details.
## š Credits
Created by [Samara](https://github.com/ahsanatha) / TSR Labs for the Clawdbot community.
Based on [Mayar.id](https://mayar.id) API and MCP server.
## š Support
- **Issues:** [GitHub Issues](https://github.com/ahsanatha/mayar-payment-skill/issues)
- **Mayar Community:** https://t.me/mcngroup
- **Mayar Docs:** https://docs.mayar.id
## ā Star History
If this skill helps you, please star the repo! ā
---
**Made with ā¤ļø for the Clawdbot community**
```
### _meta.json
```json
{
"owner": "ahsanatha",
"slug": "mayar-payment-skill",
"displayName": "Mayar.id Payment",
"latest": {
"version": "1.0.0",
"publishedAt": 1769838499418,
"commit": "https://github.com/clawdbot/skills/commit/89e9b25cb8eebe3293a3d35a648c770dab08d70d"
},
"history": []
}
```