Skip to content

Commit 69e0f91

Browse files
authored
Several skill fixes from skill-reviewer and spec alignment. (#199)
Needed to fully adjust examples to all of the recent spec changes.
1 parent 2919aa0 commit 69e0f91

4 files changed

Lines changed: 203 additions & 179 deletions

File tree

.claude/skills/grid-api/SKILL.md

Lines changed: 47 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ description: >
77
"pay [UMA address]", "send to CLABE", "send to PIX", "send to IBAN", "send to UPI",
88
"fund sandbox account", "test a payment", "on-ramp", "off-ramp", "convert crypto to fiat",
99
"convert fiat to crypto", "look up UMA", "real-time quote", "JIT funding", or any payment
10-
operations using the Grid API.
10+
operations using the Grid API CLI.
1111
allowed-tools:
1212
- Bash
1313
- Read
@@ -18,10 +18,10 @@ allowed-tools:
1818

1919
# Grid API Skill
2020

21-
You are a Grid API assistant that helps users manage global payments. You can:
21+
Assist users with global payment operations via the Grid API. Core capabilities:
2222

2323
1. **Execute API Operations** - Use `curl` to interact with the Grid API directly
24-
2. **Answer Documentation Questions** - Fetch docs from https://grid.lightspark.com or the OpenAPI spec
24+
2. **Answer Documentation Questions** - Fetch docs from <https://grid.lightspark.com/llms.txt> or the OpenAPI spec (<https://raw.githubusercontent.com/lightsparkdev/grid-api/refs/heads/main/openapi.yaml>)
2525
3. **Guide Payment Workflows** - Help users send payments to bank accounts, UMA addresses, and crypto wallets
2626

2727
## Supporting References
@@ -79,7 +79,15 @@ export GRID_BASE_URL=$(jq -r '.baseUrl // "https://api.lightspark.com/grid/2025-
7979
### Base URL
8080

8181
- **Production**: `https://api.lightspark.com/grid/2025-10-13`
82-
- **Sandbox**: May use a different base URL — check `~/.grid-credentials` for the `baseUrl` field
82+
- **Dev or local**: May use a different base URL — check `~/.grid-credentials` for the `baseUrl` field
83+
84+
### Documentation Resources
85+
86+
For questions not covered by this skill's reference files, fetch additional information from the web:
87+
88+
- **LLM-optimized docs**: Fetch `https://grid.lightspark.com/llms.txt` for a concise overview of the Grid API, or `https://grid.lightspark.com/llms-full.txt` for comprehensive documentation
89+
- **OpenAPI Spec**: Fetch `https://raw.githubusercontent.com/lightsparkdev/grid-api/refs/heads/main/openapi.yaml` for the full API schema with request/response definitions
90+
- **Published docs**: Browse `https://grid.lightspark.com` for guides, tutorials, and API reference. Any page can use the `.md` suffix for a more agent-readable format.
8391

8492
## Making API Calls
8593

@@ -139,25 +147,20 @@ curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
139147
}' \
140148
"$GRID_BASE_URL/customers" | jq .
141149

142-
# Update customer
150+
# Update customer (customerType is required)
143151
curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
144152
-X PATCH -H "Content-Type: application/json" \
145-
-d '{"fullName": "New Name"}' \
153+
-d '{"customerType": "INDIVIDUAL", "fullName": "New Name"}' \
146154
"$GRID_BASE_URL/customers/<customerId>" | jq .
147155

148156
# Delete customer
149157
curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
150158
-X DELETE \
151159
"$GRID_BASE_URL/customers/<customerId>" | jq .
152160

153-
# Generate KYC link
161+
# Generate KYC link (GET with query params)
154162
curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
155-
-X POST -H "Content-Type: application/json" \
156-
-d '{
157-
"customerId": "<customerId>",
158-
"redirectUrl": "https://example.com/callback"
159-
}' \
160-
"$GRID_BASE_URL/customers/kyc-link" | jq .
163+
"$GRID_BASE_URL/customers/kyc-link?platformCustomerId=<platformCustomerId>&redirectUri=https://example.com/callback" | jq .
161164
```
162165

163166
### Account Management
@@ -175,7 +178,7 @@ curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
175178
curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
176179
"$GRID_BASE_URL/customers/external-accounts?customerId=<customerId>" | jq .
177180

178-
# Create external account (Mexico CLABE - Individual)
181+
# Create external account (example: Mexico CLABE - Individual)
179182
curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
180183
-X POST -H "Content-Type: application/json" \
181184
-d '{
@@ -193,65 +196,10 @@ curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
193196
}
194197
}' \
195198
"$GRID_BASE_URL/customers/external-accounts" | jq .
196-
197-
# Create external account (Mexico CLABE - Business)
198-
curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
199-
-X POST -H "Content-Type: application/json" \
200-
-d '{
201-
"customerId": "<customerId>",
202-
"currency": "MXN",
203-
"accountInfo": {
204-
"accountType": "CLABE",
205-
"clabeNumber": "<18-digit-number>",
206-
"beneficiary": {
207-
"beneficiaryType": "BUSINESS",
208-
"legalName": "Company Name"
209-
}
210-
}
211-
}' \
212-
"$GRID_BASE_URL/customers/external-accounts" | jq .
213-
214-
# Create external account (India UPI)
215-
curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
216-
-X POST -H "Content-Type: application/json" \
217-
-d '{
218-
"customerId": "<customerId>",
219-
"currency": "INR",
220-
"accountInfo": {
221-
"accountType": "UPI",
222-
"vpa": "name@bank",
223-
"beneficiary": {
224-
"beneficiaryType": "INDIVIDUAL",
225-
"fullName": "Name",
226-
"birthDate": "1990-01-15",
227-
"nationality": "IN"
228-
}
229-
}
230-
}' \
231-
"$GRID_BASE_URL/customers/external-accounts" | jq .
232-
233-
# Create external account (Nigeria - REQUIRES bankName and purposeOfPayment)
234-
curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
235-
-X POST -H "Content-Type: application/json" \
236-
-d '{
237-
"customerId": "<customerId>",
238-
"currency": "NGN",
239-
"accountInfo": {
240-
"accountType": "NGN_ACCOUNT",
241-
"accountNumber": "<10-digit>",
242-
"bankName": "GTBank",
243-
"purposeOfPayment": "GOODS_OR_SERVICES",
244-
"beneficiary": {
245-
"beneficiaryType": "INDIVIDUAL",
246-
"fullName": "Name",
247-
"birthDate": "1990-01-15",
248-
"nationality": "NG"
249-
}
250-
}
251-
}' \
252-
"$GRID_BASE_URL/customers/external-accounts" | jq .
253199
```
254200

201+
For all supported account types (PIX, IBAN, UPI, NGN, US, crypto wallets) and their field requirements, read `references/account-types.md`.
202+
255203
### Quotes (Cross-Currency Transfers)
256204

257205
```bash
@@ -324,17 +272,15 @@ curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
324272
"$GRID_BASE_URL/quotes/<quoteId>" | jq .
325273
```
326274

327-
**IMPORTANT**: When specifying a destination account, you MUST also include `currency` in the destination object. This is required even though the external account already has a currency.
328-
329275
### Same-Currency Transfers
330276

331277
```bash
332278
# Transfer in (external → internal, same currency)
333279
curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
334280
-X POST -H "Content-Type: application/json" \
335281
-d '{
336-
"sourceAccountId": "<externalAccountId>",
337-
"destinationAccountId": "<internalAccountId>",
282+
"source": {"accountId": "<externalAccountId>"},
283+
"destination": {"accountId": "<internalAccountId>"},
338284
"amount": 10000
339285
}' \
340286
"$GRID_BASE_URL/transfer-in" | jq .
@@ -343,8 +289,8 @@ curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
343289
curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
344290
-X POST -H "Content-Type: application/json" \
345291
-d '{
346-
"sourceAccountId": "<internalAccountId>",
347-
"destinationAccountId": "<externalAccountId>",
292+
"source": {"accountId": "<internalAccountId>"},
293+
"destination": {"accountId": "<externalAccountId>"},
348294
"amount": 10000
349295
}' \
350296
"$GRID_BASE_URL/transfer-out" | jq .
@@ -399,13 +345,18 @@ curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
399345
# Simulate sending funds to a real-time quote
400346
curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
401347
-X POST -H "Content-Type: application/json" \
402-
-d '{"quoteId": "<quoteId>", "currency": "<code>"}' \
348+
-d '{"quoteId": "<quoteId>", "currencyCode": "<code>"}' \
403349
"$GRID_BASE_URL/sandbox/send" | jq .
404350

405351
# Simulate receiving a UMA payment
406352
curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
407353
-X POST -H "Content-Type: application/json" \
408-
-d '{"umaAddress": "<address>", "amount": 1000, "currency": "USD"}' \
354+
-d '{
355+
"senderUmaAddress": "$sender@sandbox.grid.uma.money",
356+
"receiverUmaAddress": "<receiverAddress>",
357+
"receivingCurrencyCode": "USD",
358+
"receivingCurrencyAmount": 1000
359+
}' \
409360
"$GRID_BASE_URL/sandbox/uma/receive" | jq .
410361
```
411362

@@ -444,114 +395,42 @@ Internal Account (USD) → External Account (USD) [transfer-out]
444395

445396
## Interactive Payment Workflows
446397

447-
When a user wants to send a payment, guide them through these steps:
448-
449-
### Sending to an UMA Address
450-
451-
1. Look up the receiver:
452-
453-
```bash
454-
curl -s -u "$GRID_API_TOKEN_ID:$GRID_API_CLIENT_SECRET" \
455-
"$GRID_BASE_URL/receiver/uma/%24user%40domain.com" | jq .
456-
```
457-
458-
2. Show supported currencies and any required payer data
459-
3. Create a quote with the appropriate source and destination
460-
4. Show exchange rate and fees from the quote response
461-
5. Ask for confirmation before executing
462-
6. Execute the quote
463-
464-
### Sending to a Bank Account (International)
465-
466-
1. Determine the destination country and use the appropriate account type:
467-
- **Mexico**: CLABE (18 digits)
468-
- **Brazil**: PIX (CPF 11 digits, CNPJ 14 digits, Email, Phone, or EVP 32 chars)
469-
- **India**: UPI (VPA format: `user@bankhandle`)
470-
- **Nigeria**: NGN_ACCOUNT (10-digit account + bank name + purpose)
471-
- **Europe**: IBAN + SWIFT BIC
472-
- **US**: Routing number (9 digits) + Account number
473-
- **Crypto**: Spark wallet (`spark1...`), Solana/Base/Polygon/Tron addresses
474-
475-
2. Collect required information:
476-
- Account details specific to the type
477-
- Beneficiary info (requirements vary by destination - check API response for errors)
398+
For step-by-step payment workflows, read `references/workflows.md`. Common workflows:
478399

479-
3. Create external account (see Account Management section for examples)
480-
481-
4. Create quote showing exchange rate and fees
482-
483-
5. Get confirmation and execute (or for JIT, show payment instructions)
400+
- **UMA Payment**: Receiver lookup -> Quote -> Confirm -> Execute
401+
- **International Bank Transfer**: Create external account -> Receiver lookup -> Quote -> Confirm -> Execute
402+
- **On-Ramp (Fiat to Crypto)**: Verify KYC -> Deposit fiat -> Create crypto external account -> Quote with `immediatelyExecute`
403+
- **Off-Ramp (Crypto to Fiat)**: Create fiat external account -> Deposit crypto -> Quote -> Execute
404+
- **Incoming Payment Handling**: List pending approvals -> Review -> Approve/Reject
484405

485406
### Real-Time / Just-in-Time Funded Transfers
486407

487-
Use this flow when the user asks for a "realtime quote" or "just in time" funded transfer. The quote response includes `paymentInstructions` for how to fund the transfer.
408+
Use this flow when the user asks for a "realtime quote" or "just in time" funded transfer. Only use with instant settlement methods — do not use with slow methods like ACH since quotes expire quickly.
488409

489-
**Key concept:** Real-time funding is about instant settlement, not currency type. Use this when funds will be provided at execution time via any instant payment method:
410+
**Compatible instant methods:**
490411

491412
- **Crypto:** BTC (Lightning, Spark), USDC (Solana, Base, Polygon), USDT (Tron)
492413
- **Fiat:** RTP, SEPA Instant, and other instant payment rails
493414

494-
**Important:** Only use real-time funding with instant settlement methods. Do not use with slow methods like ACH since quotes expire quickly.
415+
**Flow:**
495416

496417
1. Create a quote with `sourceType: "REALTIME_FUNDING"`. Destination can be an internal account, external account, or UMA address.
418+
2. The response includes `paymentInstructions` with **multiple funding options simultaneously** (e.g., Lightning + Spark for BTC, Solana + Base + Polygon for USDC). Show all options to the user.
419+
3. **Auto-execution**: Once the user sends funds to ANY of the provided addresses, Grid automatically detects the deposit and executes at the locked rate. Do NOT call the execute endpoint for JIT quotes. Webhooks sent: `ACCOUNT_STATUS` on deposit, `OUTGOING_PAYMENT` on completion.
420+
4. **Quote expiration**: Quotes expire in 1-5 minutes. If expired, create a new quote.
497421

498-
2. The response includes `paymentInstructions` with **multiple funding options simultaneously**:
499-
- For BTC: Lightning invoice AND Spark wallet address
500-
- For USDC: Solana wallet AND Base wallet AND Polygon wallet
501-
- For fiat: RTP details or SEPA Instant details
502-
503-
The user can choose any one of these options to fund the quote.
504-
505-
3. Show the user ALL payment options and the exchange rate. Let them choose their preferred method.
506-
507-
4. **Auto-execution**: Once the user sends funds to ANY of the provided addresses, Grid automatically:
508-
- Detects the deposit (monitors blockchain/payment rails)
509-
- Executes the transfer at the locked exchange rate
510-
- Credits the destination account
511-
- Sends webhooks: `ACCOUNT_STATUS` on deposit, `OUTGOING_PAYMENT` on completion
512-
513-
5. **No manual execution needed** - Do NOT call the execute endpoint for JIT quotes. The transfer executes automatically when funds are received.
514-
515-
6. **Quote expiration**: Quotes expire in 1-5 minutes. If expired, create a new quote. Do not use slow settlement methods (ACH) with JIT funding.
516-
517-
## Documentation Resources
518-
519-
For questions not covered by this skill's reference files, fetch additional information from the web:
520-
521-
- **LLM-optimized docs**: Fetch `https://grid.lightspark.com/llms.txt` for a concise overview of the Grid API, or `https://grid.lightspark.com/llms-full.txt` for comprehensive documentation
522-
- **OpenAPI Spec**: Fetch `https://raw.githubusercontent.com/lightsparkdev/webdev/main/openapi.yaml` for the full API schema with request/response definitions
523-
- **Published docs**: Browse `https://grid.lightspark.com` for guides, tutorials, and API reference
524-
525-
## Best Practices
422+
## Best Practices and Common Pitfalls
526423

527424
1. **Check platform config first**: Call `GET /config` to see supported currencies and required fields
528425
2. **Use smallest currency units**: All amounts are in cents/satoshis - use `decimals` field for display
529426
3. **Handle quote expiration**: Quotes expire in 1-5 minutes; be prepared to create new quotes
530427
4. **Choose the right flow**: Use prefunded for immediate execution, JIT for crypto/instant rails
531428
5. **Pipe through jq**: Always append `| jq .` for readable output, or `| jq -r .field` to extract specific values
532429
6. **URL-encode special characters**: UMA addresses contain `$` — encode as `%24` in URL paths
533-
534-
## Common Mistakes to Avoid
535-
536-
### External Account Creation
537-
538-
1. **Missing individual beneficiary fields**: For `beneficiaryType: "INDIVIDUAL"`, you MUST include in the `beneficiary` object:
539-
- `fullName`
540-
- `birthDate` (YYYY-MM-DD)
541-
- `nationality` (2-letter country code)
542-
543-
2. **Wrong field names**:
544-
- Use `bankName` (NOT `bankCode`) for Nigerian accounts
545-
- Use `purposeOfPayment` for Nigerian accounts (required)
546-
547-
3. **Missing country-specific fields**:
548-
- Nigeria (NGN_ACCOUNT): Requires `purposeOfPayment` (e.g., `GOODS_OR_SERVICES`)
549-
- Brazil (PIX): Requires `pixKey`
550-
- Europe (IBAN): Requires `swiftBic`
551-
552-
### Quote Creation
553-
554-
1. **Missing destination currency**: When specifying a destination account, you MUST also include `currency` in the destination object. This is required even though the external account already has a currency associated with it.
430+
7. **Always include destination currency in quotes**: When specifying a destination account, you MUST include `currency` in the destination object even though the external account already has a currency
431+
8. **Individual beneficiary fields are all required**: For `beneficiaryType: "INDIVIDUAL"`, you MUST include `fullName`, `birthDate` (YYYY-MM-DD), and `nationality` (2-letter code) in the `beneficiary` object
432+
9. **Use correct Nigerian field names**: Use `bankName` (NOT `bankCode`) and include `purposeOfPayment`
433+
10. **Don't forget country-specific required fields**: Brazil (PIX) requires `pixKey`, `pixKeyType`, and `taxId`; Europe (IBAN) requires `swiftBic`
555434

556435
## Error Handling
557436

0 commit comments

Comments
 (0)