Claim Submission Workflow
The Claim Submission API enables applications to submit consumer FSA/HSA claims to TPAs programmatically. Silver handles the communication to the TPA, whether that's through email, fax, mail, or SFTP upload, depending on what the TPA supports.
Environments
| Environment | Base URL |
|---|---|
| Staging | https://claim-submission-staging.withsilver.app |
| Production | https://claim-submission.withsilver.app |
Use the staging environment during development and testing. Claims sent in Staging do not get sent to providers. You will receive a staging API key from Silver during onboarding.
A test provider can be created for you in the staging environment so you can exercise the full submission flow and receive the claims to an email address of your chosing. Contact Silver to get it set up for your account.
Submission Flow
Step 1: List Providers
Retrieve the providers available for your partner account. Each provider represents a TPA that Silver can submit claims to.
curl -X GET https://claim-submission.withsilver.app/v1/providers \
-H "apiKey: your-partner-api-key"
Response:
[
{
"id": "901392c2-1d41-40f8-abcb-1995e4a7e297",
"name": "Navia",
"logo": "https://ocvtbxkudfyeyziuewun.supabase.co/storage/v1/object/public/assets/providers/901392c2-1d41-40f8-abcb-1995e4a7e297/navia-logo.png",
"type": "FSA"
},
{
"id": "a3be11fe-ba46-4a39-bac7-d3530719c276",
"name": "Navia",
"logo": "https://ocvtbxkudfyeyziuewun.supabase.co/storage/v1/object/public/assets/providers/a3be11fe-ba46-4a39-bac7-d3530719c276/navia-logo.png",
"type": "HSA"
}
]
Each provider has:
id— UUID used in subsequent API callsname— Display name of the TPAlogo— URL to the provider's logo imagetype— Account type:FSA,HSA, etc. Note that the same TPA may appear multiple times with different types
Providers and their forms may change over time as Silver adds new TPAs or TPAs update their claim processes. Always fetch the provider list dynamically rather than caching it long-term.
Step 2: Get Provider Form Requirements
Fetch the provider's details including the form fields that must be collected from the user and included in the claim submission.
curl -X GET https://claim-submission.withsilver.app/v1/providers/901392c2-1d41-40f8-abcb-1995e4a7e297 \
-H "apiKey: your-partner-api-key"
Response:
{
"id": "901392c2-1d41-40f8-abcb-1995e4a7e297",
"name": "Navia",
"logo": "https://ocvtbxkudfyeyziuewun.supabase.co/storage/v1/object/public/assets/providers/901392c2-1d41-40f8-abcb-1995e4a7e297/navia-logo.png",
"type": "FSA",
"form_requirements": [
{
"label": "First Name",
"id": "first_name",
"type": "string",
"validator": "raw",
"required": true,
"auto_fill_hints": ["given_name"]
},
{
"label": "Last Name",
"id": "last_name",
"type": "string",
"validator": "raw",
"required": true,
"auto_fill_hints": ["family_name"]
},
{
"label": "SSN or Employee ID",
"compliance_label": "Employee ID",
"id": "ssn_or_id",
"type": "string",
"validator": "number",
"required": true
},
{
"label": "Telephone Number",
"id": "telephone_number",
"type": "string",
"validator": "phone",
"required": true,
"auto_fill_hints": ["telephone_number_national"]
},
{
"label": "Email Address",
"id": "email_address",
"type": "string",
"validator": "email",
"required": true,
"auto_fill_hints": ["email"]
}
]
}
(Truncated for brevity — the actual Navia response includes 10 fields.)
Use the form_requirements array to build your claim submission form dynamically. Each field object includes:
id— The key to use inuser_form_fieldswhen submitting the claimlabel— Display text for the form fieldtype— Input type (see Form Requirements Reference)validator— Validation rule to apply (see Form Requirements Reference)required— Whether the field must be includedauto_fill_hints— Suggestions for browser/device autofillcompliance_label— Optional alternate label some partners may prefer to display instead oflabel. Please let Silver know if you have compliance requirements that do not allow you to capture Social Security Numbers.
Always fetch the provider's form_requirements dynamically rather than hardcoding fields. Requirements can change when a TPA updates their claim form.
When building user_form_fields, include every field from form_requirements — even those marked required: false. For optional fields the user doesn't fill in, submit an empty string (""). Omitting a field entirely can cause the submission to fail.
For a complete reference of all field types (string, radio, radiotext, date), validators, input formatters, and their properties, see the Form Requirements Reference.
Step 3: Upload Claimable Documents
Upload the claim documentation along with line-item services. Each upload returns a document ID to reference when submitting the claim.
There are two types of documents in a submission:
file— The primary document: the receipt or invoice for the service. Must be base64-encoded.supporting_documents— Optional additional evidence such as a Letter of Medical Necessity (LMN). Also base64-encoded.
curl -X POST https://claim-submission.withsilver.app/v1/claimable_documents \
-H "apiKey: your-partner-api-key" \
-H "Content-Type: application/json" \
-d '{
"user_id": "your-user-id",
"document_type": "receipt",
"file": {
"base64": "JVBERi0xLjQKJcfs...",
"mime_type": "application/pdf"
},
"claimable_services": [
{
"service_date_start": "2026-01-10",
"service_date_end": "2026-01-10",
"service_provider": "Downtown Physical Therapy",
"service_description": "Physical therapy session — 60 min",
"claimable_amount": 150.00
}
],
"supporting_documents": [
{
"base64": "iVBORw0KGgoAAAANS...",
"mime_type": "image/png"
}
]
}'
Response: Returns the claimable document ID as a string (UUID).
Request fields:
| Field | Required | Description |
|---|---|---|
user_id | Yes | Your identifier for the user |
document_type | Yes | Type of document (e.g. receipt) |
file | Yes | Base64-encoded primary document (receipt/invoice) with base64 and mime_type |
claimable_services | No | Array of line-item services on this document |
supporting_documents | No | Array of base64-encoded supporting documents (e.g. LMN) |
Claimable service fields:
| Field | Required | Description |
|---|---|---|
service_date_start | Yes | Service start date (YYYY-MM-DD) |
service_date_end | Yes | Service end date (YYYY-MM-DD) |
service_provider | Yes | Name of the service provider |
service_description | Yes | Description of the service |
claimable_amount | Yes | Amount in dollars (e.g. 150.00) |
sku | No | Product identifier |
sku_type | No | Type of SKU (e.g. UPC) |
You can also manage services on a document after creation:
- List services:
GET /v1/claimable_documents/{id}/claimable_services - Remove a service:
DELETE /v1/claimable_documents/{document_id}/claimable_services/{service_id}
Step 4: Submit the Claim
Submit the claim referencing the uploaded documents, the chosen provider, the required form fields, and the member's signature.
curl -X POST https://claim-submission.withsilver.app/v1/claims \
-H "apiKey: your-partner-api-key" \
-H "Content-Type: application/json" \
-d '{
"user_id": "your-user-id",
"provider_id": "901392c2-1d41-40f8-abcb-1995e4a7e297",
"plan_period_start": "2026-01-01",
"plan_period_end": "2026-12-31",
"user_form_fields": {
"first_name": "Jane",
"last_name": "Smith",
"ssn_or_id": "123456",
"telephone_number": "5551234567",
"email_address": "jane@example.com",
"employer_name": "Acme Corp",
"street": "123 Main St",
"city": "Seattle",
"state": "WA",
"zip_code": "98101"
},
"signature": "iVBORw0KGgoAAAANSUhEUgAA...",
"claimable_documents": ["e4b0a99b-1887-46b1-b026-0907f8e59474"]
}'
Response:
{
"claim_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"user_provider_id": "f9e8d7c6-b5a4-3210-fedc-ba9876543210"
}
Request fields:
| Field | Required | Description |
|---|---|---|
user_id | Yes | Your identifier for the user |
provider_id | Yes | Provider UUID from Step 1 |
plan_period_start | No | Plan year start date (YYYY-MM-DD) |
plan_period_end | No | Plan year end date (YYYY-MM-DD) |
user_form_fields | Yes | Object with keys matching id values from the provider's form_requirements |
signature | Yes | Base64-encoded PNG of the member's signature |
claimable_documents | Yes | Array of document IDs from Step 3 (must include at least one with claimable services) |
Idempotency
The POST /v1/claimable_documents and POST /v1/claims endpoints support idempotency. Include an Idempotency-Key header with a unique string to safely retry requests without creating duplicates.
curl -X POST https://claim-submission.withsilver.app/v1/claims \
-H "apiKey: your-partner-api-key" \
-H "Idempotency-Key: unique-request-id-12345" \
-H "Content-Type: application/json" \
-d '{ ... }'
Behavior:
- If the key matches a completed request with the same body, the original response is returned.
- If the key matches a request that is still processing, a
409 Conflictis returned. - If the key was used with a different request body, a
422 Unprocessable Entityis returned. - Keys expire after 24 hours.
Best Practices
- Fetch form requirements dynamically — Provider forms can change at any time. If you save form fields for a user, you might get a 4xx error if the fields have changed.
- Upload documents before submitting — All document uploads must complete before the claim is submitted.
- Store the claim ID — Save the returned
claim_idfor tracking and customer support purposes. - Include all line-item services — When uploading documents, include the
claimable_servicesarray with accurate service dates, amounts, and descriptions. - Use idempotency keys — Always include an
Idempotency-Keyheader on POST requests to safely handle retries. - Fetch the provider list Dynamically — Call
GET /v1/providerswhen a user is present to show the latest providers avaialble. If you save this to a user's profile, you might get a 4xx error if the support has changed.