- CRITICAL: Read Rule Files Before Implementing
- The #1 cause of bugs is using wrong HTTP methods or stream configurations.
- For EVERY endpoint:
- Read
- rules/{EndpointName}.md
- Check HTTP method (PUT for create, POST for update, DELETE for delete)
- Verify stream ID format (UUID, not hex)
- Use hex chain IDs (0x1, 0x89), not names (eth, polygon)
- Reading Order:
- This SKILL.md (core patterns)
- Endpoint rule file in
- rules/
- Pattern references in
- references/
- (for edge cases only)
- Setup
- API Key (optional)
- Never ask the user to paste their API key into the chat.
- Instead:
- Check if
- MORALIS_API_KEY
- is set in the environment (try running
- [ -n "$MORALIS_API_KEY" ] && echo "API key is set" || echo "API key is NOT set"
- ).
- If not set, offer to create the
- .env
- file with an empty placeholder:
- MORALIS_API_KEY=
- Tell the user to open the
- .env
- file and paste their key there themselves.
- Let them know: without the key, you won't be able to test or call the Moralis API on their behalf.
- If they don't have a key yet, point them to
- admin.moralis.com/register
- (free, no credit card).
- Environment Variable Discovery
- The
- .env
- file location depends on how skills are installed:
- Create the
- .env
- file in the project root (same directory the user runs Claude Code from). Make sure
- .env
- is in
- .gitignore
- .
- Verify Your Key
- curl
- "https://api.moralis-streams.com/streams/evm?limit=10"
- \
- -H
- "X-API-Key:
- $MORALIS_API_KEY
- "
- Base URL
- https://api.moralis-streams.com
- Important:
- Different from Data API (
- deep-index.moralis.io
- ).
- Authentication
- All requests require:
- X-API-Key: $MORALIS_API_KEY
- HTTP Methods (CRITICAL)
- Action
- Method
- Endpoint
- Create stream
- PUT
- /streams/evm
- Update stream
- POST
- /streams/evm/{id}
- Delete stream
- DELETE
- /streams/evm/{id}
- Get streams
- GET
- /streams/evm
- Replace addresses
- PATCH
- /streams/evm/{id}/address
- Common mistake:
- Using POST to create streams. Use PUT instead.
- Stream Types
- Type
- Description
- tx
- Native transactions
- log
- Contract event logs
- erc20transfer
- ERC20 token transfers
- erc20approval
- ERC20 approvals
- nfttransfer
- NFT transfers
- internalTx
- Internal transactions
- Quick Reference: Most Common Patterns
- Stream ID Format (ALWAYS UUID)
- // WRONG - Hex format
- "0x1234567890abcdef"
- // CORRECT - UUID format
- "YOUR_STREAM_ID"
- Chain IDs (ALWAYS hex)
- "0x1"
- // Ethereum
- "0x89"
- // Polygon
- "0x38"
- // BSC
- "0xa4b1"
- // Arbitrum
- "0xa"
- // Optimism
- "0x2105"
- // Base
- Event Signatures (topic0)
- "Transfer(address,address,uint256)"
- // ERC20/NFT Transfer
- "Approval(address,address,uint256)"
- // ERC20 Approval
- Status Values (lowercase only)
- "active"
- // CORRECT - normal operating state
- "paused"
- // CORRECT - manually paused
- "error"
- // CORRECT - auto-set when webhook success rate <70%
- "terminated"
- // CORRECT - unrecoverable, after 24h in error
- "ACTIVE"
- // WRONG
- Common Pitfalls (Top 5)
- Using POST to create streams
- - Use
- PUT
- instead
- Wrong base URL
- - Use
- api.moralis-streams.com
- , NOT
- deep-index.moralis.io
- Hex stream ID
- - Must be UUID format, not hex
- String chain names
- - Use hex (0x1), not names (eth)
- Uppercase status
- - Use lowercase ("active", "paused")
- Not returning 200 on test webhook
- - Stream won't start unless your endpoint returns 2xx on the test webhook sent during create/update
- See
- references/CommonPitfalls.md
- for complete reference.
- Triggers (Read-Only Contract Calls)
- Enrich webhook data with on-chain reads (e.g.,
- balanceOf
- ). Triggers execute
- view
- /
- pure
- functions and attach results to webhook events. Supports dynamic selectors (
- $contract
- ,
- $from
- ,
- $to
- ). See
- references/Triggers.md
- for complete reference with examples.
- Native Balances in Webhooks
- Configure
- getNativeBalances
- to include native token balances (ETH, BNB, etc.) in webhook payloads. Requires Business plan+. See
- references/UsefulStreamOptions.md
- for configuration details.
- Delivery and Error Handling
- Two webhooks per event
-
- Unconfirmed (
- confirmed: false
- ) + Confirmed (
- confirmed: true
- ). Idempotent handlers required.
- Streams auto-terminate after 24 hours in error state
- (webhook success rate <70%). This is
- unrecoverable
- — you must create a new stream.
- Test webhook
- Sent on every create/update. Must return 200 or stream won't start. See references/DeliveryGuarantees.md and references/ErrorHandling.md . Webhook Security Webhooks are signed with your streams secret (different from API key). Header: x-signature Algorithm: sha3(JSON.stringify(body) + secret) const verifySignature = ( req , secret ) => { const provided = req . headers [ "x-signature" ] ; const generated = web3 . utils . sha3 ( JSON . stringify ( req . body ) + secret ) ; if ( generated !== provided ) throw new Error ( "Invalid Signature" ) ; } ; See references/WebhookSecurity.md for complete examples. Testing Endpoints WEBHOOK_URL = "https://your-server.com/webhook"
List streams (requires limit)
curl "https://api.moralis-streams.com/streams/evm?limit=100" \ -H "X-API-Key: $MORALIS_API_KEY "
Create stream (PUT, not POST)
curl -X PUT "https://api.moralis-streams.com/streams/evm" \ -H "X-API-Key: $MORALIS_API_KEY " \ -H "Content-Type: application/json" \ -d '{ "webhookUrl": "' ${WEBHOOK_URL} '", "description": "Test stream", "tag": "test", "topic0": ["Transfer(address,address,uint256)"], "allAddresses": false, "chainIds": ["0x1"] }'
Pause stream (POST to status)
curl
-X
POST
"https://api.moralis-streams.com/streams/evm/
First page
curl "...?limit=100" -H "X-API-Key: $KEY "
Next page
curl
"...?limit=100&cursor=