Testing Bulk Enrollment
Introduction
This guide drives the bulk-enrollment pipeline in the sandbox environment end to end: create a network bulk feed, trigger a synthetic ingestion, and watch cards and transactions appear, with no real network file delivery. Every request below runs against https://api.sandbox.astrada.co with a bearer token from Get a token.
In production, the network (Visa, Mastercard, Amex) delivers card files to Astrada on a schedule you do not control. In sandbox, you play the network: POST /simulate/ingestion/{network} writes a synthetic file into the same ingestion pipeline, drawing cards from fixed test card pools. Everything downstream of the file is the real pipeline, so the webhooks and resources you see here are what you will see in production.
1. Create a bulk feed
A feed registers the network reference that your files arrive under. Create one per network you want to test; this walkthrough uses Visa VCF. Use any of your subaccounts as {subaccountId} (or create one as in Testing Bank Linking). The networkReference format is network-specific, and the feed's network and type must match the simulate endpoint you call in step 2.
POST /network-bulk-feeds HTTP/1.1
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
{
"networkReference": "1_123_45_6789",
"network": "VISA",
"type": "VCF",
"subaccountId": "{subaccountId}"
}curl -X POST https://api.sandbox.astrada.co/network-bulk-feeds \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"networkReference": "1_123_45_6789",
"network": "VISA",
"type": "VCF",
"subaccountId": "{subaccountId}"
}'{
"networkReference": "1_123_45_6789",
"network": "VISA",
"type": "VCF",
"subaccountId": "{subaccountId}"
}Response (201 Created): the feed resource with state: submitted.
{
"id": "75ea3c99-6bf5-4b16-8f68-0cdc43d75806",
"subaccountId": "...",
"network": "VISA",
"networkReference": "1_123_45_6789",
"state": "submitted",
"type": "VCF",
"panFormat": "encrypted",
"createdAt": "2026-08-28T09:00:00Z",
"updatedAt": "2026-08-28T09:00:00Z"
}Per-network bodies:
| Network | network / type | networkReference format | Notes |
|---|---|---|---|
| Visa VBDS | VISA / VBDS (default) | RPIC 1_123_45_6789 | Pull-based. cardCount (1-20, sandbox-only, VBDS-only) sizes an automatic starter fetch at creation, so cards appear without step 2. |
| Visa VCF | VISA / VCF | RPIC 1_123_45_6789 | File-based; nothing happens until step 2. |
| Mastercard SmartData | MASTERCARD / SMARTDATA (default) | Delivery ID G1234567 | File-based. |
| Amex GL | AMEX / GL (default) | Recipient ID R123456 | File-based. panFormat: tokenized (sandbox-only, Amex-only) tests the tokenized-PAN variant; default is encrypted. On a tokenized feed newCardCount is unsupported and an omitted cardCount draws the whole tokenized pool (see the Sandbox API Reference). |
One feed per reference
POST /network-bulk-feedsreturns409 Conflictif a feed already exists for thatnetworkReference. Reuse the existing feed and go straight to step 2; the simulate endpoints can be called on the same feed as often as you like.
2. Drive an ingestion
Each network has a simulate endpoint that writes a synthetic file for an existing feed. All four take the same three knobs and return 202 Accepted with an empty body; processing is asynchronous.
POST /simulate/ingestion/vcf HTTP/1.1
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
{
"networkReference": "123_45_6789",
"cardCount": 0,
"newCardCount": 5,
"transactionsPerCard": 3
}curl -X POST https://api.sandbox.astrada.co/simulate/ingestion/vcf \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"networkReference": "123_45_6789",
"cardCount": 0,
"newCardCount": 5,
"transactionsPerCard": 3
}'{
"networkReference": "123_45_6789",
"cardCount": 0,
"newCardCount": 5,
"transactionsPerCard": 3
}The other three are the same call with a different path and reference format: POST /simulate/ingestion/smartdata ("networkReference": "G1234567"), POST /simulate/ingestion/amex-gl ("networkReference": "R123456"), and POST /simulate/ingestion/vbds ("networkReference": "1_12345_67890_54321"). Full body-param tables and response codes are in the Sandbox API Reference. One format quirk: VCF accepts the PIC without the region segment (123_45_6789) or the full RPIC used at feed creation; VBDS always takes the full RPIC.
How the three knobs behave on repeat calls:
cardCountreplays the head of the network's test-card pool: the same cards every call, deduplicated once enrolled, like a re-delivered production file.newCardCountdraws cards this subaccount has never seen, so each call enrolls that many new cards and fires theircardsubscription.createdwebhooks.transactionsPerCardgenerates that many transactions per included card, with fresh references and recent dates on every call, so repeats always producetransaction.created/transaction.updatedwebhooks, including for already-enrolled cards.
Amex GL is the only network that differsThe knobs behave identically on Visa VCF, Mastercard SmartData, and Visa VBDS: an omitted
cardCountdefaults to5, andnewCardCountis always available. Amex GL is the exception on two points. An omittedcardCountdraws3on an encrypted feed, or the whole enrollable tokenized pool on apanFormat: tokenizedfeed, rather than5. And a tokenized feed has no new-card region, so anynewCardCount > 0on it is rejected with400. See the Sandbox API Reference for the per-endpoint tables.
Feed activation, and the VCF one-card safety netA feed moves from
submittedtoactiveonly once an ingestion creates at least one new card link. The first ingestion normally does this off the head cardscardCountdraws by default. Visa VCF adds a safety net: if the subaccount has already enrolled those head cards, a head-only replay would deduplicate into nothing and leave the feed stuck, so on a feed that has never completed an ingestionnewCardCount: 0still draws one never-seen card (at most once per feed). This is VCF-only. SmartData, VBDS, and Amex GL activate off the head cards their defaultcardCountdraws (5, or3/ the tokenized pool for Amex), so they have no such forced draw.
3. See what was created
Processing usually completes within a minute. Observe the results through the normal read APIs and webhooks:
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
"https://api.sandbox.astrada.co/network-bulk-feeds/{networkBulkFeedId}"Response (200 OK): the feed, now state: active.
Then:
GET /cards?subaccountId={subaccountId}lists the enrolled cards, on the network's reserved test BIN.GET /card-subscriptions?subaccountId={subaccountId}shows one subscription per card withenrollmentType: "network-bulk"and thenetworkBulkFeedIdback-reference.GET /cards/{cardId}/cardholderreturns synthetic cardholder data (firstName,lastName,postalCode,corporate.employeeId;emailonly on Visa VCF).- With
transactionsPerCard > 0,GET /transactions?subaccountId={subaccountId}fills up as clearings process.
Webhooks fired along the way, in the order you should see them: networkbulkfeed.statechanged (submitted to active), one cardsubscription.created per new card, then transactionmessage.created / transaction.created / transaction.updated per generated transaction. Payloads are in the Webhook Event Types reference.
The transactions above are the generic clearings generated during ingestion. Once you have enrolled cards, you can also drive a specific transaction shape against one of them with Simulate a transaction scenario — a catalog of predefined flows (purchases, refunds, partial clearings, FX conversions, hotel and car-rental pre-auths, the Amex auth lifecycles, and the multi-country Uber ride-share scenarios), useful for exercising authorization-to-expense matching against real network message sequences.
4. Test card pools
Simulated cards are drawn from fixed, reserved pools, matched by exact full PAN:
| Network | BIN | PAN length |
|---|---|---|
| Visa | 404507 | 16 |
| Mastercard | 510755 | 16 |
| Amex | 370000 | 15 |
The full PAN lists and the head/new region semantics are on Test Card Pools. You rarely need the raw lists: cardCount and newCardCount draw from them for you.
Next steps
- Simulate a transaction scenario: drive a specific predefined transaction shape — from simple purchases and refunds to FX conversions and the multi-country Uber ride-share flows — against a card you enrolled above.
- Sandbox API Reference: full body params and response codes for every simulate endpoint.
- Testing Bank Linking: the bank rail in the same environment.
- Network Bulk Enrollment: how the production feeds work.
Updated about 4 hours ago
