设计与多媒体

sportsinc-sportslink

试用

Sports Inc SportsLink API adapter — pull a dealer's invoices ("documents") from the Sports Inc SportsWeb Invoice Center and mark them consumed. Sports Inc is a buying group that does NOT send individual vendor invoices; its SportsLink REST API is where the invoices live. Use when you need to retrieve Sports Inc invoices for payables — "get the Sports Inc invoices", "pull SportsLink documents", "fetch this month's SI invoices to match against POs". This is the SOURCE adapter only: it authenticates, pages, normalises each SI document into a common invoice shape (po_number, invoice_number/date, lines[], charges, total, is_credit), and marks documents historical once imported. Some documents are scanned rather than EDI, so the API returns their header totals with NO line items (`has_lines: false`) — every retrieval names those in `needs_line_recovery`, and they are not billable as returned. For each, this skill logs in to the SportsWeb portal, downloads the invoice PDF, OCRs the scanned ve

它能做什么

Sports Inc SportsLink API adapter — pull a dealer's invoices ("documents") from the Sports Inc SportsWeb Invoice Center and mark them consumed. Sports Inc is a buying group that does NOT send individual vendor invoices; its SportsLink REST API is where the invoices live. Use when you need to retrieve Sports Inc invoices for payables — "get the Sports Inc invoices", "pull SportsLink documents", "fetch this month's SI invoices to match against POs". This is the SOURCE adapter only: it authenticates, pages, normalises each SI document into a common invoice shape (po_number, invoice_number/date, lines[], charges, total, is_credit), and marks documents historical once imported. Some documents are scanned rather than EDI, so the API returns their header totals with NO line items (`has_lines: false`) — every retrieval names those in `needs_line_recovery`, and they are not billable as returned. For each, this skill logs in to the SportsWeb portal, downloads the invoice PDF, OCRs the scanned vendor invoice into text for the agent to read, and then checks the extracted lines against the API's own merchandise total before any of it is billable. It is customer-agnostic (every Sports Inc dealer uses this same API) and touches no ERP — pair it with a payables workflow (e.g. `drivethru-payable-matching`) to match against POs and create the bill.

技能文档

Sports Inc is a buying group: BaconCo (and every other SI dealer) buys through Sports Inc, and Sports Inc does not email individual vendor invoices — they're published in the SportsWeb Invoice Center and exposed through the SportsLink REST API. This skill is the source adapter for that API. It does one job: hand a payables workflow a clean, normalised list of invoices, and mark them consumed once they've been imported. It never touches Odoo.

The single helper is scripts/sportslink.py:

# The un-imported inbox: every active document, normalised. Scanned documents
# come back with no lines and are named in `needs_line_recovery` — see the
# retrieval procedure below. Do NOT pass `ediOnly: true` for a billing run: it
# filters those documents out of the result entirely, so they are never billed
# and simply age.
python3 scripts/sportslink.py list '{"active": true, "lines": true}'

# A specific document (ignores the active-only filter)
python3 scripts/sportslink.py get '{"poNumber": "P13189"}'

# Mark documents consumed — AFTER they've been billed (honors SPORTSINC_DRY_RUN)
python3 scripts/sportslink.py mark-historical '{"siDocNumbers": [12345, 23456]}'

# A2A-safe action for agent-to-agent calls (structured request/response contract)
python3 scripts/sportslink.py get-for-a2a '{"customer_ref": "DEALER-001", "date_range": {"start": "2024-01-01", "end": "2024-12-31"}, "statuses": ["open"]}'

# Header-only (scanned) document: get its PDF, read it yourself, then get checked
python3 scripts/sportslink.py fetch-invoice-doc '{"si_doc_number": 23962348}'
python3 scripts/sportslink.py reconcile-lines '{"si_doc_number": 23962348, "lines": [...]}'

Every command prints one JSON object, or {"error": {...}} with a non-zero exit. Needs SPORTSINC_API_KEY (if unset, exits config_error — stop and tell the user to configure it; never ask for the key in chat).

⚠ Retrieval procedure — required, every time

A Sports Inc retrieval is not finished when list returns. Some documents come back with header totals and no line items, because Sports Inc scanned the supplier's invoice instead of receiving it as EDI. Those are not billable as returned — there is nothing to match against a PO.

Every list / get / get-for-a2a result names them:

"needs_line_recovery": [24682750, 24684277],
"credits": [24690002],
"next_step": "2 document(s) have no line detail from the API …"

If needs_line_recovery is non-empty, you must resolve every document in it before billing any of them. For each one:

# 1. Fetch it. Logs in to the portal, downloads the PDF, and OCRs the scanned
#    vendor invoice into text. Active tab first, Archived automatically after.
python3 scripts/sportslink.py fetch-invoice-doc '{"si_doc_number": 24684277}'

# 2. Read the returned `text` and extract the line items yourself.
#    See references/pdf_extraction.md — which pages to skip, the field mapping,
#    and the rules (transcribe don't compute, never infer a quantity).

# 3. Hand them back to be checked against the API's own merchandise total.
python3 scripts/sportslink.py reconcile-lines '{"si_doc_number": 24684277, "lines": [...]}'

Step 3 returns status: "verified" — a normalised invoice with real lines[], indistinguishable downstream from an EDI one — or status: "needs_review" with the variance named.

Non-negotiables:

  • Bill only a verified invoice. needs_review means the extracted lines do not tie to Sports Inc's own header; escalate and leave the document active.
  • Never bill a document from header totals alone. A docTotal with no lines behind it cannot be matched to a PO, and that is the whole point of matching.
  • Never skip a document because it is inconvenient. It reappears on the next run, unbilled, and ages.
  • credits (is_credit: true) are never billed at all — they go to a human, whatever their line detail looks like.
  • Exactly-once is unchanged: mark-historical only after the bill exists.

If fetch-invoice-doc reports portal_tab: "archived", the document has already been marked historical — which happens only after a bill was created. Check whether it has already been paid before creating another.

Normalised invoice shape

list/get return {count, total_count, invoices: [...]}, each invoice:

{
  "source": "sports_inc",
  "po_number": "P13189",          // dealer PO number → the match key to a PO
  "si_doc_number": 12345,          // SI's document id → used to mark-historical
  "invoice_number": "…",           // supplierDocNumber (falls back to si_doc_number)
  "invoice_date": "…",             // supplierDocDate, else siDocDate
  "due_date": "…", "supplier": "…",
  "is_credit": false,               // credit memo → handle separately, never a bill
  "has_lines": true,                // false for scanned/OCR docs (header totals only)
  "placeholder_lines": 0,           // empty rows the API returned and we dropped
  "placeholder_note": null,         // what they said, e.g. "SEE VENDOR INVOICE FOR DETAIL."
                                    // has_lines false ⇒ this document appears in
                                    // `needs_line_recovery`; see the retrieval
                                    // procedure above before billing it
  "lines_source": "pdf",            // present only when lines were recovered from a PDF
  "total": 0,                       // docTotal
  "charges": {"merchandise", "freight", "freight_allowance", "si_upcharge",
              "svc_handle", "sales_tax", "excise_tax", "discount"},
  "lines": [{"item","upc","description","size","color","unit",
             "qty_ordered","qty_shipped","qty_backordered",
             "list_price","discount_pct","net_price","extension"}]
}

This is the same shape a PDF-extracted invoice would have, so a payables workflow reconciles it without caring that it came from SportsLink.

Rules that matter

  • Don't pull before ~10:30am ET — SI's internal processing runs first; earlier reads can be incomplete. Schedule accordingly.
  • Line data is EDI-only, so scanned documents need the portal. They come back with header totals and no usable lines (has_lines: false) and are named in needs_line_recovery. Recover each one via the retrieval procedure above; if that cannot produce a verified result, escalate rather than blind-bill. ediOnly: true exists to fetch only EDI documents — useful for a narrow query, wrong for a billing run, because the documents it filters out are still owed and will simply age.
  • A scanned document returns a placeholder line, not an empty array. One row with no item and no UPC, zeroes throughout, and the description "SEE VENDOR INVOICE FOR DETAIL." — SI's own instruction, the same sentence printed on the PDF's cover page. A line counts only if it identifies a product (item number or UPC) or carries a non-zero number; a description alone does not, or that row reads as real. Dropped rows surface as placeholder_lines / placeholder_note. See references/sportslink_api.md.
  • is_credit: true is a credit memo — route it to a human / vendor credit, never create it as a payable.
  • Exactly-once — the golden rule. Import first, mark-historical after the bill is created. This adapter deliberately does not use the API's moveToHistorical=true GET flag (which marks on read, before billing) — a crash between read and bill would silently drop the invoice. The natural loop: list active → bill each in the ERP → mark-historical the ones that succeeded; failures/escalations stay active and are retried next run.
  • Paging is automatic (all: true, the default). Max 1000 docs/call on SI's side; the helper pages to the end (capped at 50 pages as a backstop).

Header-only documents: recovering lines from the PDF

Sports Inc scans some supplier invoices instead of receiving them as EDI. Those documents arrive with header money but no lines, and the line detail exists only in the PDF in the SportsWeb Invoice Center — there is no API for it. This skill recovers those lines in three beats, with you as the middle one:

fetch-invoice-doc  →  you read the PDF  →  reconcile-lines
   (Python: I/O)      (the only fuzzy step)   (Python: arithmetic)

No extraction model is involved anywhere: OCR transcribes the scan, the agent interprets the text, and arithmetic checks the result. Scanned pages are OCR'd before you see them, so what lands in context is text rather than a 300dpi image — the images stay on disk for when the text is not good enough.

What a download contains. Not one invoice — a stack of documents, each being a landscape SI cover page (native text, no line detail, it says SEE VENDOR INVOICE FOR DETAIL.) followed by the vendor invoice, usually a 300dpi scan. That scan is where the line items are; the SI cover is useless for extraction, since if it held line detail the API would have had it too. One PDF routinely bundles several such pairs — one per SI document on the PO — so fetch-invoice-doc groups the pages into documents and flags which group is the one you asked for.

Build status. Working end to end. Extraction and reconciliation are covered by scripts/_selftest.py (33 tests) and were run against a real two-document download (PO P13554), with both documents' lines reconciling to the cent, and the whole chain has since run end to end on a live document: API lookup → placeholder detected → portal login → download → segment → OCR → reconcile → verified, variance 0.00 (SI 24684277, 183.20 + 215.20 = 398.40). The portal automation was confirmed on the live portal: a capture-portal run logged in, searched, parsed both rows, ticked one, and pulled back a 121,619-byte PDF in 17.9s. fetch-invoice-doc has then been run end to end for a single si_doc_number — it matched that one row, downloaded a 2-page document (not the 4-page PO bundle), and extracted the scanned vendor invoice to a PNG for reading.

Headless is confirmed — a cold run completed the same chain in 20.7s. Still open, and listed in references/sportsweb_flow_notes.md: every run has been from a local machine, so a datacenter IP is untested (Auth0 treats a cloud runner as a new device); multi-page results are not handled (hdnMaxPage is read but the driver takes page 1 only); and the Archived-tab fallback has never been exercised. {"pdf_path": "/path/to/invoice.pdf", "si_doc_number": 24682750} still works for a PDF pulled by hand.

The portal flow

www.sportsinc.us  →  click DEALER LOGIN  →  sportsweb.us.auth0.com/u/login
  →  swv3.sportsinc.com/home        ← the home screen, and the only search box
  →  type the PO, click Search      → swv2h.sportsinc.com/Member/InvoiceCenter/…
  →  tick the matching row(s)  →  Downloads  →  "PDF File"

Three steps in that chain are counter-intuitive, and each cost a debugging round: the login redirect 403s if navigated to directly (it must be clicked from the public site); home and the Invoice Center are different hosts, so a session check pointed at the wrong one always fails and forces a needless re-login; and the Invoice Center 404s on a direct hit even though its URL appears in the address bar after a search.

Nothing waits on networkidle — the Vue home screen holds connections open and may never reach it, and a long wait for an event that will not come looks exactly like a hang. Every wait targets a concrete element, and each step is recorded with elapsed milliseconds in the trace that capture-portal returns. Downloading is two clicks: Downloads opens an in-page dialog, and PDF File inside it merges every ticked document into one PDF.

Selectors bind to what is durable. WebForms ids are _, so controls are matched on the suffix (table[id$='grdInvoices'], input[id$='_chkItem']); Auth0's classes are per-build hashes and are never used, its ids are. Rows are matched on their SI Doc No. cell, never by position — downloading the wrong invoice is the one failure reconciliation cannot catch, since another document's lines are internally consistent and simply tie to a different header.

One trap worth knowing about, because it would fail quietly: the grid's frozen-header script clones the entire `` into body cells, so a naive cell read returns every column heading followed by the value. Cell text is read with a tree walker that skips cloned headers, and any value that still carries one is rejected rather than trimmed.

capture-portal — run this first

python3 scripts/sportslink.py capture-portal '{"search": "P13554"}'
python3 scripts/sportslink.py capture-portal '{"search": "P13554", "probe_download": true}'

Add {"archived": true} to exercise the Archived-tab path (tab switch, column selection, re-search) — the one branch of the flow that has never run.

A read-only diagnostic: logs in, runs the search, and reports the landing URL, which elements it located, the portal's own hidden state fields, and the rows it parsed — plus a full-page screenshot and the page HTML. With probe_download it walks the download dialog and records how the file arrives (a download event or an inline response), its size, and whether it starts with %PDF-. Nothing is modified either way. Add {"headless": false} to watch it run.

download_format reaches the dialog's other options (pdf_zip, csv, csv_items, pdf_and_csv); pdf is the default and the only one this skill uses. In particular the portal's CSV with Header and Item Detail export is not a shortcut around reading the scan — for a header-only document it comes back with no item detail, because it is fed by the same EDI line data the SportsLink API exposes. If the CSV had the lines, the API would have had them.

fetch-invoice-doc

python3 scripts/sportslink.py fetch-invoice-doc '{"si_doc_number": 24682750}'

Fetches the PDF, classifies every page, and makes the readable parts readable:

  • documents — the stack split into {si_cover_page, detail_pages, si_doc_number_candidates, supplier_doc_candidates, detail_is_scanned, matches_requested}. Read the group with matches_requested: true and reconcile one document at a time.
  • textevery readable page, native or OCR'd, page-marked. A transcribed page is labelled [OCR: rapidocr, mean confidence 0.98] so it can never be mistaken for the document's own text layer — only one of the two can misread a digit.
  • image_paths — PNGs extracted from the scanned pages (…-p2.png for page 2). Kept as the cross-check even when OCR succeeded. The scans sit two levels deep inside Form XObjects, so they are pulled out explicitly rather than left to a PDF renderer that may not exist on the host.
  • pages[].kindsi_cover | text | image | blank, per page.
  • readable_text_covers_all_pages — the flag that matters: every page has text, from either source. (has_text_layer is true whenever any page has a native layer, and the SI covers always do, so a naive read of it concludes a scanned invoice is fully readable when it contains no line detail at all. text_covers_all_pages means native text alone was enough.)
  • ocr_pages / ocr_engine / pages_without_text — which pages were transcribed, by what, and which could not be read at all.
  • pdf_path — the whole PDF, kept as a fallback when any page is scanned.

Multi-page results are handled: a single document is found by narrowing the grid search to its SI Doc No. rather than paging, and a whole-PO fetch reads every page and merges the per-page downloads (selection does not survive paging). pages_searched and download_parts in the response say what it took.

Identify what to fetch with si_doc_number (one document — preferred, less to disambiguate) or po_number (every supplier invoice on that PO in one browser trip; the Invoice Center searches by PO and returns a row per invoice, and its Downloads button combines the ticked rows into one PDF).

Active then Archived, automatically. A miss on the Active tab re-runs the search on Archived — no flag, because a caller usually cannot know which tab a document is on. portal_tab in the response says where it was found, and a hit on Archived also returns already_historical_warning: Sports Inc marks a document historical only after it has been billed, so finding it there is a duplicate-payment tell, not a routing detail. stash (auto | always | never) controls what gets written. Other options: pdf_path (read a PDF off disk instead of the portal), force (re-read a document that does have EDI lines — normally refused), and inline username / password / base_url portal overrides.

The response carries the document's identity — PO, invoice number, date, supplier, credit flag — but deliberately not its money. Extraction should be blind to the total it will be checked against; an agent that knows the merchandise total can unconsciously bend a misread line to hit it, which is the exact error the next step exists to catch.

You read it

references/pdf_extraction.md is the extraction guide: which pages to read and which to skip, how to confirm you are on the right vendor invoice, the field mapping, the rules (transcribe don't compute, never infer a quantity, bill the shipped quantity, one object per printed row, skip subtotals and freight), and a worked example from a real download. Read it before extracting.

reconcile-lines

python3 scripts/sportslink.py reconcile-lines '{"si_doc_number": 23962348, "lines": [...]}'

Normalises your lines into the canonical shape and checks them against the header fetched fresh from SportsLink — never against numbers you supply, since a check against what the same agent just read verifies nothing:

  1. Per-line mathqty_shipped × net_price = extension, ±$0.02.
  2. The anchor — extensions must sum to merchandiseTotal, allowing a cent of rounding per line. Falls back to docTotal minus charges when the header's merchandise total is missing (an OCR gap).
  3. Doc-total reassembly — informational.

Returns status: "verified" — an invoice in the ordinary normalised shape, with lines_source: "pdf", that the payables workflow bills exactly like an EDI one — or status: "needs_review" with a per-issue breakdown.

A needs_review invoice is never billed. Re-reading the PDF and re-running is fine and often the fix (a variance equal to one line's extension usually means a missed row on page two). Adjusting a line to make the total tie is not: the whole value of this path is that a model's reading gets audited by arithmetic it doesn't control. If a second reading agrees with the first, escalate and leave the SI document active.

reconcile-lines marks nothing historical — the exactly-once seam stays exactly where it is.

Where this fits

Source adapter (this) → payables workflow (drivethru-payable-matching) → ERP adapter (drivethru-odoo / drivethru_mcp). This skill owns only the "get the invoices + mark them consumed" half; matching to POs, correcting pricing, and creating the draft bill live in the workflow. See that skill's references/sportsinc_payables.md for the end-to-end procedure.

That procedure currently escalates every header-only document to a human. Once the portal capture lands and fetch-invoice-doc works unattended, its "No lines? → escalate" step should instead route through the PDF fallback and escalate only on needs_review.

References

  • references/sportslink_api.md — the API itself: parameters, document/line fields, and the semantics behind them.
  • references/pdf_extraction.md — how to read a scanned invoice PDF into line items. Read before extracting.
  • references/sportsweb_flow_notes.md — the portal capture checklist. Start here to finish the browser flow.

Offline tests for the extraction/reconciliation halves: python3 scripts/_selftest.py (needs pypdf; reportlab optional).

Agent-to-Agent (A2A) Mode

The get-for-a2a action provides a contract-driven interface for inter-agent communication. Deploy this skill on a dedicated Sports Inc agent and let the internal agent that needs invoices (e.g. an Accounts Payable agent) reach it via a delegation connection in the Knoxville platform.

Where SPORTSINC_API_KEY comes from (credential broker)

The SPORTSINC_API_KEY is bound to the calling agent (the one that represents your company — e.g. Accounts Payable), not to this Sports Inc agent. On that agent's delegation connection to this one, the operator chooses to share SPORTSINC_API_KEY with the connection.

The value is pulled on demand, not pushed. When this agent handles a delegated call (X-Knox-Caller-Kind: agent), the runtime (not you) fetches the shared SPORTSINC_API_KEY for this conversation and places it into the skill's execution environment for this turn only, before your exec runs. The platform verifies this agent is the target of the delegated conversation and that the connection shares the credential, and logs the access in agent_connection_audit_log. sportslink.py then reads SPORTSINC_API_KEY from the environment exactly as it does standalone. You do not see this value in your context — it is deliberately kept out of the model prompt.

So on a delegated turn, just run the tool. Your first action for a Sports Inc request is the exec call itself — e.g. python3 scripts/sportslink.py get-for-a2a '{...}'. Do not, before running it:

  • call get_my_bundle, get_delegated_credentials, or any tool to look for or "verify" the key — it is intentionally invisible to you, so you will always find nothing and wrongly conclude you have no access;
  • spawn a sub-agent (sessions_spawn) to do this skill's job — you are the agent that runs it;
  • tell the caller you lack the key or access before you have actually run the script and read its output.

If the script itself reports an auth_error (or config_error), the caller's connection hasn't shared the credential — surface that error rather than guessing, and never print the credential value into the chat reply.

Request Contract

get-for-a2a params (all optional):

{
  "customer_ref": "DEALER-001",
  "date_range": { "start": "2024-01-01", "end": "2024-12-31" },
  "include_historical": false
}
  • include_historical (default false) → active/un-imported invoices only; set true to also include historical/consumed docs.
  • customer_ref is advisory only — the SportsLink API key is per-dealer and the API has no customer filter, so this field does not scope the result. It is echoed back in metadata.customer_ref for the caller's audit.

Response Contract

Unlike the other actions (which exit non-zero on error), get-for-a2a always exits 0 and reports failure in-band, so an A2A caller reads one envelope shape either way.

Success:

{
  "success": true,
  "invoices": [ { "source": "sports_inc", "po_number": "P13189", "si_doc_number": 12345, "total": 1500.00, "lines": [] } ],
  "metadata": { "count": 42, "total_count": 50, "pages_read": 1, "source": "sports_inc", "customer_ref": "DEALER-001", "include_historical": false },
  "error": null
}

Error:

{
  "success": false,
  "invoices": null,
  "metadata": null,
  "error": {
    "type": "auth_error|connection_error|api_error|validation_error",
    "message": "Human-readable error message",
    "retriable": true
  }
}

Replying to a delegated task — compact markdown, not raw JSON

The JSON envelope above is the contract for a synchronous send_message call, where the caller reads the object programmatically. But when the payables agent reaches you as an async delegated task (it start_tasks you a request and you report back with an outcome/summary), your reply is free text another agent reads, and that summary field has a hard ~20,000-character limit. A raw JSON dump of several POs' invoices overflows it and is silently truncated — which hands the payables agent a half-parsed payload and corrupts its billing. (This is exactly what happened once: five POs of pretty-printed JSON, cut off mid-object.)

So on a delegated task, run get-for-a2a / list as usual, then hand back a compact markdown breakdown in your outcome summary — never paste the raw JSON. Markdown carries all the same data in a fraction of the characters and the payables agent reads it directly (it does not need strict JSON). Include every field it needs, terse, and do not wrap it in a code fence (fences add bulk and confuse parsing):

  • One ## heading per PO.
  • One bullet per SI document: si_doc_number, invoice_number, invoice_date, due_date, is_credit, has_lines, and the money from charges + total (merchandise, freight, si_upcharge, total).
  • Under each document with has_lines: true, one terse line per item: item, upc, size, qty_shipped, net_price, extension, description. For a has_lines: false document write detail no and omit item lines.

Example — keep it this tight (normalised field values, no code fence around it in your real reply):

## P09409
- SI 23962348 | inv# 6164920830 | 2026-02-16 | due 2026-05-10 | credit no | detail yes | merch 51.00 freight 8.58 upcharge 0.48 total 60.06
  - JP1477 | 197612326076 | S | qtyShip 1 | net 12.75 | ext 12.75 | TF SHRT TIGHT M BLACK
  - JP1477 | 197612326083 | M | qtyShip 3 | net 12.75 | ext 38.25 | TF SHRT TIGHT M BLACK
- SI 23972779 | inv# 6164929812 | 2026-02-17 | due 2026-05-10 | credit no | detail yes | merch 180.61 freight 0.00 upcharge 1.45 total 182.06
  - JJ1179 | 196476717082 | L | qtyShip 1 | net 25.50 | ext 25.50 | GG SL HD MGREYH

If even the compact form would be too large (many POs, many lines), never cut it silently: return the POs you can and end with an explicit NOTE: truncated — returned N of M POs, ask again for the rest, so the caller knows to re-request rather than bill from a partial payload.

The retriable flag indicates whether the caller should retry (transient connection errors) or escalate (auth/config errors).

相关技能

Payable matching for BaconCo — reconcile vendor documents in Odoo's Documents app against their purchase orders and correct incorrect PO line pricing. Use for requests like "check the Purchasing folder against the POs and fix the pricing", "match the vendor invoice / order confirmation / acknowledgement to its PO", "AP price matching / invoice-to-PO matching / three-way match", "reconcile the vendor documents and mark the POs checked", or "go through the Purchasing folder". The flow: read every document in a Documents-app folder (extracting text out-of-context so large batches don't bloat the context window — falling back to a page render + OCR/vision for scanned or custom-encoded PDFs that won't extract as text), pull the PO number / line items / unit prices from each, compare to the purchase order line by line, correct any wrong `price_unit`, post a "checked" log note on the PO (internal, never a "Send message"), and FILE every document into the `Matched` or `Questions` subfolder — e

SportsDataIO (sportsdata.io). Use this skill for ANY SportsDataIO request — reading, creating, and updating data. Whenever a task involves SportsDataIO, use this skill instead of calling the API directly.

Invoice Ninja (invoiceninja.com). Use this skill for ANY Invoice Ninja request — reading, creating, and updating data. Whenever a task involves Invoice Ninja, use this skill instead of calling the API directly.

Generate branded invoice and billing-document PDFs for agentic development services, including deposits, milestones, retainers, change orders, pass-through e...

16 次安装

Deterministic SanMar API toolkit covering the four order-lifecycle pillars — purchase orders, inventory, tracking, and invoicing — behind typed CLI tools over SanMar's SOAP web services, PromoStandards services, and SFTP data feeds. Submit and pre-validate POs; check real-time per-warehouse inventory (PromoStandards v2) or bulk FTP feeds; get package-level tracking (Order Shipment Notification) and parse the FTP Daily Shipment Status file; retrieve invoices (InvoicePort — by PO, invoice number, order date, date range, or unpaid) and parse the FTP Daily Invoice / EDI-810 files, all normalized to a common payables shape. Also search products, pull myPrice pricing, parse PO PDFs, resolve marketing colors to mainframe codes, and file portal returns. Use whenever the user needs to read from or write to SanMar for apparel sourcing, pricing, ordering, tracking, or accounts-payable.

2 次安装

Live sports alerts for Soccer, NFL, NBA, NHL, MLB, F1 and more. Real-time scoring with the free ESPN API. Track any team from any major league worldwide.

226 次安装2 星标