01Run it
Straight from the command's own help.
p202 conversion import a2hosting-feb.csv --dry-runp202 conversion import a2hosting-feb.csv --dry-run --check-clicksp202 conversion import export.csv --subid-column 'Sub ID 2' --time-column 'Sale Date' --timezone America/New_Yorkp202 conversion import conversions.json --force --json02What you get
--json, --csv or --ndjson for scripts, or -q for ids only. An AI agent gets compact JSON without asking. All output formats03Build your command
Pick values and the command line writes itself, quoted and ready to paste.
p202 conversion importSet flags below; the command updates as you type.
04Flags
9 flags, plus the global flags every command takes.
| Flag | What it does |
|---|---|
| --check-clicksbool | With --dry-run, also read each click's conversions to show click_not_found and duplicate rows |
| --dry-runbool | Show the plan and write nothing (no request unless --check-clicks) |
| --force, -fbool | Skip the confirmation prompt |
| --payout-columnstring | Header of the payout column (default: auto-detect; with no payout column the campaign's default payout applies) |
| --subid-columnstring | Header of the column holding the Prosper202 subid (default: auto-detect) |
| --time-columnstring | Header of the conversion time column (default: auto-detect; with no time column the server records now) |
| --time-formatstring | Go time layout of the time column, e.g. '01/02/2006 15:04' (default: unix or ISO dates) |
| --timezonestring · default UTC | Zone of times written without one: UTC, an IANA name, or an offset like -05:00 |
| --txid-columnstring | Header of the transaction id column (default: auto-detect) |
05How it works
Reads a network's conversion export — a CSV file with a header row, or a JSON array of objects — and records each line as a conversion on the click its subid names.
Columns (auto-detected from the header, case and punctuation ignored; the flags override): subid required: subid, sub_id, aff_sub, sub1, click_id, clickid, s2 (--subid-column) payout optional: payout, commission, amount, revenue (--payout-column); $ and thousands separators (1,234.50) are dropped, a decimal comma (12,50) is refused; absent = the campaign's default payout transaction id optional: transaction_id, order_id, txid (--txid-column) time optional: date, time, conversion_date, created_at (--time-column); unix seconds or ms, or 2026-02-03[ 14:05[:00]] in --timezone (default UTC), RFC 3339, or any Go layout given with --time-format; absent = now More than one candidate header for a column is refused: name the one to use.
The subid is read as the postback (gpb.php) reads it: the click id, digits only, no leading zero. Rows are marked invalid (with the reason) or duplicate_in_file (the same click and transaction id as an earlier row; without a transaction id a click converts once, as the postback does). A negative payout with a transaction id reverses that sale; negative rows are sent after the sales, so a newest-first report reverses the right one.
--dry-run shows that plan without contacting the server; add --check-clicks to also read each click's conversions (GET /clicks/{id}/conversions, read-only, once per click). Without --dry-run the clicks are always read first, then you confirm (--force skips; --staged records proposals instead), then each ready row is sent as POST /conversions with an Idempotency-Key derived from its click, transaction id, payout and time.
Statuses: created, duplicate (the click already has it: same transaction id, or any conversion for an id-less row, or the key was replayed, or the server answered it as a duplicate or as a deleted conversion's transaction id), conflict (the click has the transaction id with another payout or time; not sent), click_not_found, failed (with the server's message), staged, invalid, duplicate_in_file (ready in a dry run). Re-running the same file is safe: recorded rows come back as duplicate. Exit 5 if any row failed or conflicts; re-running the same command then sends only the rows not yet recorded.
06For agents
Running this from an agent
- Read the same facts as JSON:
p202 commands conversion import --json. - With
AI_AGENT,CLAUDECODEor another agent variable set, output is compact JSON and errors arrive on stderr as a JSON envelope with ahint. - Exit codes: 0 ok, 1 bad input, 2 auth, 3 network, 4 server error, 5 partial failure.
- This command writes. Add
--stagedto record it as a proposal a person applies withp202 change apply.
{
"path": "p202 conversion import",
"use": "import <file>",
"short": "Record a network's conversion export (CSV or JSON) against its clicks, safely re-runnable",
"long": "Reads a network's conversion export — a CSV file with a header row, or a JSON array of\nobjects — and records each line as a conversion on the click its subid names.\n\nColumns (auto-detected from the header, case and punctuation ignored; the flags override):\n subid required: subid, sub_id, aff_sub, sub1, click_id, clickid, s2 (--subid-column)\n payout optional: payout, commission, amount, revenue (--payout-column); $ and\n thousands separators (1,234.50) are dropped, a decimal comma (12,50) is\n refused; absent = the campaign's default payout\n transaction id optional: transaction_id, order_id, txid (--txid-column)\n time optional: date, time, conversion_date, created_at (--time-column); unix\n seconds or ms, or 2026-02-03[ 14:05[:00]] in --timezone (default UTC),\n RFC 3339, or any Go layout given with --time-format; absent = now\nMore than one candidate header for a column is refused: name the one to use.\n\nThe subid is read as the postback (gpb.php) reads it: the click id, digits only, no\nleading zero. Rows are marked invalid (with the reason) or duplicate_in_file (the same\nclick and transaction id as an earlier row; without a transaction id a click converts\nonce, as the postback does). A negative payout with a transaction id reverses that sale;\nnegative rows are sent after the sales, so a newest-first report reverses the right one.\n\n--dry-run shows that plan without contacting the server; add --check-clicks to also read\neach click's conversions (GET /clicks/{id}/conversions, read-only, once per click).\nWithout --dry-run the clicks are always read first, then you confirm (--force skips;\n--staged records proposals instead), then each ready row is sent as POST /conversions\nwith an Idempotency-Key derived from its click, transaction id, payout and time.\n\nStatuses: created, duplicate (the click already has it: same transaction id, or any\nconversion for an id-less row, or the key was replayed, or the server answered it as a\nduplicate or as a deleted conversion's transaction id), conflict (the click has the\ntransaction id with another payout or time; not sent), click_not_found, failed (with\nthe server's message), staged, invalid, duplicate_in_file (ready in a dry run). Re-running\nthe same file is safe: recorded rows come back as duplicate. Exit 5 if any row failed or\nconflicts; re-running the same command then sends only the rows not yet recorded.",
"runnable": true,
"example": "p202 conversion import a2hosting-feb.csv --dry-run\n p202 conversion import a2hosting-feb.csv --dry-run --check-clicks\n p202 conversion import export.csv --subid-column 'Sub ID 2' --time-column 'Sale Date' --timezone America/New_York\n p202 conversion import conversions.json --force --json",
"flags": [
{
"name": "check-clicks",
"type": "bool",
"default": "false",
"usage": "With --dry-run, also read each click's conversions to show click_not_found and duplicate rows",
"required": false
},
{
"name": "dry-run",
"type": "bool",
"default": "false",
"usage": "Show the plan and write nothing (no request unless --check-clicks)",
"required": false
},
{
"name": "force",
"shorthand": "f",
"type": "bool",
"default": "false",
"usage": "Skip the confirmation prompt",
"required": false
},
{
"name": "payout-column",
"type": "string",
"default": "",
"usage": "Header of the payout column (default: auto-detect; with no payout column the campaign's default payout applies)",
"required": false
},
{
"name": "subid-column",
"type": "string",
"default": "",
"usage": "Header of the column holding the Prosper202 subid (default: auto-detect)",
"required": false
},
{
"name": "time-column",
"type": "string",
"default": "",
"usage": "Header of the conversion time column (default: auto-detect; with no time column the server records now)",
"required": false
},
{
"name": "time-format",
"type": "string",
"default": "",
"usage": "Go time layout of the time column, e.g. '01/02/2006 15:04' (default: unix or ISO dates)",
"required": false
},
{
"name": "timezone",
"type": "string",
"default": "UTC",
"usage": "Zone of times written without one: UTC, an IANA name, or an offset like -05:00",
"required": false
},
{
"name": "txid-column",
"type": "string",
"default": "",
"usage": "Header of the transaction id column (default: auto-detect)",
"required": false
}
]
}