This skill should be used when the user asks to query MetLife Pet Insurance, check pet insurance claims, list claims, get claim details, download EOBs, download policy documents, or interact with the mypets.metlife.com API.
How this skill is triggered — by the user, by Claude, or both
Slash command
/metlife-pet-insurance:metlife-petsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are a helper for interacting with the MetLife Pet Insurance API.
You are a helper for interacting with the MetLife Pet Insurance API.
Authentication is handled by metlife.sh in the repo root. It supports:
.metlife-cache/.tokenIf ensure_auth returns AUTH_NEEDED, ask the user for their MetLife login credentials:
"I need to log into your MetLife account. What's your email and password for mypets.metlife.com?"
Then call:
source metlife.sh
LOGIN_RESULT=$(metlife_login "[email protected]" "their_password")
If login returns MFA_OTP_SENT (exit code 2): MetLife requires email verification. Ask the user to check their email for a verification code, then call:
source metlife.sh
metlife_verify_otp "123456"
If login completes without MFA: Tokens are saved automatically.
Important (zsh compatibility): Always run metlife.sh with bash or ensure the calling shell is bash. The script uses bash-specific features and avoids zsh reserved variable names.
Always source metlife.sh and call ensure_auth at the top of every Bash tool invocation:
cd /path/to/claude-metlife
source metlife.sh
AUTH_RESULT=$(ensure_auth)
if [ "$AUTH_RESULT" = "AUTH_NEEDED" ]; then
echo "AUTH_NEEDED"
exit 0
fi
If AUTH_NEEDED is returned, stop and ask the user for credentials. Do not proceed with API calls.
MetLife uses two separate API gateways. The helper script handles headers for each automatically.
apis.metlife.com) — pets, policies, rewardsUse metlife_apim for these endpoints:
| Endpoint | Description |
|---|---|
GET $APIM_BASE/pets | List all pets |
GET $APIM_BASE/pets/{petId}/profile | Pet profile details |
GET $APIM_BASE/pets/{petId}/profileImage | Pet profile image (base64 JPEG) |
GET $APIM_BASE/policies | List all policies |
GET $APIM_BASE/policies/{policyId} | Policy details |
GET $APIM_BASE/rewards/active | Active rewards |
GET $APIM_BASE/rewards/isAvailable | Rewards availability |
api.metlife.com) — claims, customer, paymentsUse metlife_ibm for these endpoints:
| Endpoint | Description |
|---|---|
GET $IBM_BASE/cl/v1/claim/all?petId={petId}&policyId={policyId} | List all claims (pass policyId= empty for all policies) |
GET $IBM_BASE/cl/v1/incident/{claimSourceId}/{claimId}/incidents | Claim incidents (line-item groups per pet/condition; claimSourceId is typically 1) |
GET $IBM_BASE/cl/v1/incident/{incidentId}/lineItems | Incident line items (individual charges, denial reasons, exception messages) |
GET $IBM_BASE/cl/v1/document-details?policyId={policyId}&claimSourceId=1&claimId={claimId} | List claim documents (EOBs and submitted docs) |
GET $IBM_BASE/cl/v1/document-details?..&isBlobRequest=true&filePath={filePath}&claimDocumentType=2 | Download submitted docs (invoices, SOAP notes) |
GET $IBM_BASE/cl/v1/document-details?..&isBlobRequest=true&filePath={filePath}&claimDocumentType=1 | Download EOB |
GET $IBM_BASE/p/v1/policy/{policyId}/policyPacket | Policy packet PDF (binary response, save directly) |
GET $IBM_BASE/cu/v1/customer/details | Customer profile |
You can also use metlife_api which auto-routes to the correct gateway based on the URL.
The filePath comes from the docDetails array in the document list response. Use claimDocumentType=1 (not 2). The response may return the document in either docDetails[].document or eobDetails[].eobDocument -- check both fields.
If a download returns null, try the other claimDocumentType and try both petIds on the policy. The API is inconsistent -- some documents only download with a specific petId even if tagged for multiple pets. URL-encode filePaths with spaces.
RESPONSE=$(metlife_ibm "$IBM_BASE/cl/v1/document-details?policyId=$POLICY&claimId=$CLAIM&petId=$PET&isBlobRequest=true&filePath=$FILE_PATH&claimDocumentType=1")
echo "$RESPONSE" | python3 -c "
import sys,json,base64
d=json.load(sys.stdin)
m=d.get('model',{})
for e in (m.get('eobDetails') or []):
if e.get('eobDocument'):
open('output.pdf','wb').write(base64.b64decode(e['eobDocument'])); break
else:
for doc in (m.get('docDetails') or []):
if doc.get('document'):
open('output.pdf','wb').write(base64.b64decode(doc['document'])); break
"
The filePath comes from the eobDetails array (eobFilePath field). Use claimDocumentType=1:
RESPONSE=$(metlife_ibm "$IBM_BASE/cl/v1/document-details?policyId=$POLICY&claimId=$CLAIM&petId=$PET&isBlobRequest=true&filePath=$EOB_PATH&claimDocumentType=1")
echo "$RESPONSE" | python3 -c "import sys,json,base64; data=json.load(sys.stdin); eob=data.get('model',{}).get('eobDetails',None); [open('eob.pdf','wb').write(base64.b64decode(e['eobDocument'])) for e in (eob or []) if e.get('eobDocument')]"
All API responses and downloaded documents are cached in .metlife-cache/.
.metlife-cache/
├── .token # Auth tokens (4 lines: bearer, refresh, expiry, session_id)
├── claims/
│ ├── {policyId}_{petId}_all.json # All claims list
│ └── {claimSourceId}_{claimId}.json # Individual claim details
├── documents/
│ ├── {policyId}_{claimId}_{petId}_list.json # Document list
│ └── {policyId}_{claimId}_{petId}/ # Downloaded files
│ └── {filename}.pdf
└── policies/
└── {policyId}_packet.pdf # Policy packet
is_cacheable before writing to cache. Never cache error responses.mkdir -p.Caching pattern:
CACHE_FILE=".metlife-cache/claims/${POLICY}_${PET}_all.json"
if [ -f "$CACHE_FILE" ]; then
RESPONSE=$(cat "$CACHE_FILE")
else
RESPONSE=$(metlife_ibm "$IBM_BASE/cl/v1/claim/all?petId=$PET&policyId=$POLICY")
if is_cacheable "$RESPONSE"; then
mkdir -p "$(dirname "$CACHE_FILE")"
echo "$RESPONSE" > "$CACHE_FILE"
else
echo "ERROR: API call failed. Response: $RESPONSE" >&2
fi
fi
metlife.sh and call ensure_auth at the top of every Bash tool call. If AUTH_NEEDED, ask for credentials and call metlife_login.ensure_auth before multi-step operations to avoid mid-operation failures.is_cacheable to avoid writing error responses to cache.metlife_ibm for claims/documents/policy endpoints, metlife_apim for pets/policies list/rewards, or just metlife_api (auto-routes)..metlife-cache/.token.When the user first provides their credentials (or says "sync" or "fetch everything"):
metlife_apim "$APIM_BASE/pets" — get pet IDs and names.metlife_apim "$APIM_BASE/policies" — get policy IDs.After sync, all reads come from cache unless the user asks to refresh.
$ARGUMENTS
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub graysoncadams/claude-metlife --plugin metlife-pet-insurance