API Report Card · Banks · Methodology v1.1
Column
Where the points came from.
Five categories, each worth a fixed share of the 100 points. A category earns the fraction of its checks it passes, times its maximum.
Functional Coverage
Design & Reliability
Access Control
Docs & AI-Ready
Access & Cost
Letter grades are absolute, never curved.
The same numeric bands apply to every platform. Nothing here is scored relative to the rest of the board.
What this means for you.
One paragraph per category, in plain language.
1 · Functional Coverage
The strongest part of Column's API, and genuinely rare. You can open bank accounts, read exact balances broken into available, pending, locked and holding, pull every transaction, send money on any rail, and then cancel, clear, return, reverse or stop-pay it. All of it from code, and all of it confirmed working live rather than promised in documentation. If you can describe a money movement, you can almost certainly automate it here.
2 · Design & Reliability
The parts that protect your money are excellent. Double-clicking send cannot double-send, and that was proven live rather than just documented: two identical calls with the same idempotency key produced one transfer. Retries, pagination, bulk export and webhook security are all handled properly, and Column publishes real uptime numbers. The soft spots are the ones you hit while building and maintaining. Error responses do not use the right HTTP status codes, so your code has to read the body rather than trust the status, and a failed login returns a completely empty response. There is no API version you can pin, so a future change could alter behaviour under you with only a changelog post as warning. And although every response carries a trace id that would be perfect for a support ticket, Column never documents it, so you cannot count on it being honoured.
3 · Access Control
Exactly what you want before pointing an AI agent or a new automation at your bank account. You can mint a key that can only read, or one that can send ACH credits but not wires, or one that touches a single account, and you can require a human to approve every transfer that key initiates. No amount of clever prompting gets around that, because keys are structurally forbidden from approving transfers at all, including their own. You get a full free sandbox with its own keys that cannot reach live money, and you can revoke any key yourself the moment something looks wrong.
4 · Docs & AI-Ready
If you or an AI coding assistant sit down to build against Column, you have what you need: a complete machine-readable spec that tools can generate working code from, and the entire documentation set published in clean formats built for AI retrieval. Documentation quality is not a barrier here. The one soft spot is knowing when something changes. The changelog is genuinely detailed when it appears, but it appears in irregular batches with gaps of several months, and since there is no API version you can pin, that changelog is your only early warning.
5 · Access & Cost
You can be building today. Sign up, create a sandbox key yourself, and the entire API, every rail and every endpoint, works immediately against realistic simulated money, at no cost and with nobody to ask. Nothing is held back for an enterprise tier. The only thing standing between the sandbox and moving real dollars is the bank compliance review any real bank must run on you, which is the law rather than an upsell.
Every check, and why it scored that way.
The same 27 checks are applied to every platform. What changes is which are N-A and what the core objects mean for that kind of software. Each mark below is quoted from the run's own report.
Category 1 · Functional Coverage
15 / 15Object coverage
weighted coverage = 100% (19/19 weight; no critical object absent). Every object in the fixed classification is present with the operations its role requires; the read-only ones (balances, transactions, statements) are computed or immutable records and are N-A for writes under the weighted-coverage method. [openapi.json paths listed in the coverage map; live GET /bank-accounts and GET /transfers, 2026-09-09]
Core operational actions
weighted coverage = 100% (11/11 applicable weight; no critical write workflow absent). Accounts create/update (weight 3), payment initiation create (weight 3), reconciliation report creation (weight 2), webhook subscription create/update/delete (weight 2), counterparty create (weight 1) - all observed live. This is emphatically not an observational API. [live POST /bank-accounts, PATCH /bank-accounts/{id}, POST /transfers/book, POST /transfers/ach, POST /counterparties, POST /webhook-endpoints, 2026-09-09]
Delete or lifecycle actions
weighted coverage = 100%; no critical lifecycle action absent. Live-observed transitions: book_3J5oT1oNh6dlBdKDkvkjyWnCs93 HOLD → CANCELED via POST /transfers/book/{id}/cancel; book_3J5oT1Dxzhj88x2Fozwp376VDuI HOLD → COMPLETED via POST /transfers/book/{id}/clear; acht_3J5oSwtzkKrvXYtcqBVMIOAXmJn INITIATED → CANCELED via POST /transfers/ach/{id}/cancel; bank account closed via DELETE /bank-accounts/{id}. Return, reverse, stop-payment and approve/reject paths documented per-rail in openapi.json.
Change notification
175 distinct documented event types across ACH (22), check (39), realtime (31), wire (29), SWIFT (23), loan (14), reporting (10) and book (5) families, covering initiation, settlement, completion, return and cancellation state changes - well above the 0.85 weighted threshold for critical-plus-important changes. Independently, efficient incremental polling is available (created.gt/gte/lt/lte plus types and object_ids filters on GET /events; created.* on per-rail lists). Live-verified: book.transfer.completed event evnt_3J5oLbHntWcksXYYICu70PCwqhI was generated by a test transfer and matched to the subscription; created.gte=2026-01-01 returned 3 events while created.gte=2030-01-01 correctly returned 0. [working-with-the-api/events-and-webhooks; live GET /events and GET /webhook-deliveries/endpoint/{id}]
Category 2 · Design & Reliability
7.5 / 10Modern API conventions
Resource-oriented REST over HTTPS with standard verbs (GET/POST/PATCH/DELETE), JSON responses, and a published OpenAPI 3.0.3 document. Live-verified across GET, POST, PATCH and DELETE, all returning content-type: application/json; charset=utf-8. [openapi.json; live observations 2026-09-09]
Consistent typing
Core typing is excellent: across 811 typed field names in the spec, amount is integer in all 40 schemas that use it, currency_code is string in all 38, id string in all 40, has_more boolean in all 31, and the live balance reads returned integers exactly as specified. The exact limitation: 13 field names carry conflicting declared types across schemas, and several sit on paths an integration actually traverses. check_number is typed string in UnifiedTransfer (the array element of ListTransfers, the response schema for GET /transfers) but integer/int64 in CheckTransfer (the response for GET /transfers/checks/{id}), so the same value changes type depending on which endpoint you read it from. Worse for round-tripping, account_usage is array in CreateBusinessEntity and UpdateBusinessEntity but string in BusinessDetails, so a value written as an array reads back as a string on the same object; purpose_of_account splits string on the three business-entity schemas against array on the three person-entity schemas, so one client model cannot cover both entity types. The remainder: payment_related_info (string on ACHTransfer/CreateAchTransfer, array on IATAddenda), national_id (object on person schemas, string on IBAN), fx_rate (number on card schemas, string on SWIFT), tax_year (string on wire schemas, integer on tax-form schemas), total_fee, total_principal, total_interest and sale_price (string on loan-sale summaries, integer on LoanSummary, despite all being documented "in cents"), and the generic containers data and details. A rendered example on the balance-history endpoint additionally prints available_balance_credit as the string "100" while BankAccountSummary declares it an integer, so the inconsistency reaches rendered examples and not only schemas.
Structured errors
The error body is excellent and was confirmed live: every failure returned type, a populated stable machine-readable code, a human-readable message, a documentation_url, and a details object naming the offending field. Observed codes included invalid_resource_id_format, bank_account_not_found, invalid_currency_code, mandatory_parameter_missing (with details.required_field), invalid_field_value (with details.unknown_field), invalid_record_status and resource_not_found. The exact limitation is HTTP status semantics. Column's own errors table defines 404 as "Not Found. The requested resource does not exist," but a GET for a well-formed, nonexistent bank account (bacc_3ImcPgxvreKMx9KaatOZw8LYbnZ) returned HTTP 400 with bank_account_not_found, not 404 - so an integration cannot branch on status code alone and must read the body. Separately, an invalid credential returned HTTP 401 with a zero-byte body (content-length: 0), so authentication failures carry no structured error at all. [working-with-the-api/errors; live probes 2026-09-09]
Duplicate prevention
Idempotency-Key is documented for 25 consequential write endpoints, covering every money-moving path (ACH, book, wire, international wire, realtime, check deposit and issue, reversals) plus account, entity and document creation. Live-verified: two identical POST /transfers/book calls with the same key apitest-grading-1788960191 both returned transfer id book_3J5oGA5oMiVjoKXau0MdA0ekBa6 with idempotency_key echoed on the object - one transfer, not two. [working-with-the-api/idempotency; live double-send 2026-09-09]
Graceful handling under load
429 Too Many Requests is documented together with explicit numeric backoff guidance: "Retry using exponential backoff with jitter, starting after 1 second and doubling after each 429 response, up to a maximum delay of 30 seconds. Stop after 5 retries." That satisfies the check's numeric-guidance branch. (No RateLimit/Retry-After headers were present on observed 200 responses, and no rate limit was triggered during testing; the check expressly does not penalize a vendor for not publishing exact limit numbers.) [working-with-the-api/errors, HTTP status table]
Pagination for large collections
Documented cursor pagination via starting_after/ending_before with limit (default 10, max 100) and a has_more flag, on "All endpoints that list objects," with an explicit stable ordering guarantee ("return objects in inverse chronological order, such that the most recently created object will be returned first"). GET /transfers additionally returns total_results_count. Live-verified: a full traversal at limit=2 returned 3 unique bank accounts across 2 pages with no duplicates and correct has_more termination. [working-with-the-api/pagination; live traversal 2026-09-09]
Bulk or incremental export
A dedicated reporting path retrieves full datasets without per-record calls: POST/GET /reporting produces bank_account_transaction and bank_account_summary reports "available in CSV, JSON, and Parquet formats," containing all transactions affecting balances in a period. Incremental sync is independently available via created.gt/gte/lt/lte plus cursor pagination on 21 list endpoints. Noted without deduction: there is no updated_since-style filter anywhere in the spec (21 endpoints expose created.; none expose updated.), so change detection for mutated records relies on the events feed rather than on re-querying by modification time; the check is satisfied by the dedicated export path independently of this. [guides/reporting; openapi.json /reporting; live GET /reporting HTTP 200]
Webhook security and delivery reliability
All three required elements are documented: (1) signatures - "every webhook event payload is signed with a signature that is passed through as the HTTP header Column-Signature… HMAC with SHA-256, by applying the webhook endpoint's signing secret as the key"; (2) a retry policy - "If an event delivery failed, our system will retry up to 25 times within 3 days with exponential backoffs. The first retry happens one minute after the original failed delivery"; and (3) replay/idempotency guidance for consumers - "An event may occasionally be delivered multiple times to a webhook endpoint with the same unique event ID. We advise you to guard against duplicated event receipts by making your event processing idempotent," reinforced by an explicit warning that ordering is not guaranteed. Live-verified: endpoint whep_3J5oK7wqDhGzWvlzWxOroxgJSTl was created and returned a per-endpoint signing secret (whsr_…); a triggered book transfer produced event evnt_3J5oLbHntWcksXYYICu70PCwqhI, which was correctly matched to the book.transfer.completed subscription and recorded in GET /webhook-deliveries/endpoint/{id} with scheduled_at and status. Disclosed: the subscription deliberately pointed at a non-routable host so no sandbox data left Column, so the delivery status was FAILED by design and the HMAC signature itself was documentation-graded, not observed. [working-with-the-api/events-and-webhooks; live registration, trigger and delivery-record read 2026-09-09]
Concurrency and conflict control
The half that is present: conflicting writes are rejected by a documented state guard, not silently applied. invalid_record_status is a published error code (llms-full.txt line 1824), and live probes confirmed it: cancelling an already-CANCELED transfer returned invalid_record_status with details.status: "canceled", and clearing an already-COMPLETED transfer returned invalid_record_status with details.status: "completed". The half that is missing: there is no optimistic concurrency mechanism - a GET on a bank account returned no ETag or Last-Modified header, the object carries no version field (keys observed: balances, bic, created_at, currency_code, default_account_number, default_account_number_id, description, fdic_insurance, id, interest_config_id, is_interest_bearing, is_overdraftable, overdraft_reserve_account_id, owners, routing_number, status, type), If-Match is unsupported, and no concurrency limits or concurrent-write behavior are documented anywhere in the corpus. Conflicts also return 400 rather than 409.
Versioning and backward compatibility
There is no version contract a client can rely on. No version identifier is exposed in the path or in a header: live probes of /v1/bank-accounts and /api/bank-accounts both returned 404, and no version-related response header appears on any observed response. A full-corpus search for backward-compatibility language ("backward", "breaking", "non-breaking", "additive", "deprecation policy") across all 21,243 lines of llms-full.txt returned no policy - the only hit is the unrelated phrase "backward pagination." The sole version signal is info.version: "1.4" inside the OpenAPI document, which describes the specification file and cannot be selected or pinned by a caller. (Deprecation announcements do appear in the changelog; that is change-communication currency and is scored in C4.4, not double-counted here.)
Request traceability
A unique correlation identifier is present on every observed response, including errors and the bodiless 401: request-id: apir_3J5nnjsNeJOOoE1fb5a4VScmuvN, apir_3J5nsmZjs8bhwiTyjAV6HG0mfbS, apir_3J5nulcvJrpSFBtoyk0s0A2u5qE, apir_3J5numnEVH0zVPtMDPwadkjhzYN - all distinct, alongside a constant platform-id. The exact limitation: the header is entirely undocumented. A targeted search of the complete documentation corpus for the request-id header returned no hits, so nothing establishes that the identifier is stable, retained, or usable when contacting Column support - which is what the check's yes requires.
Service availability and status transparency
https://status.column.com is a public Atlassian Statuspage showing "All Systems Operational" with four separately monitored components (Sandbox, Production, FedWire, FedACH), each carrying a 90-day uptime percentage (100.0% at time of access), a dated incident history log, a "View historical uptime" link, and email/SMS/Slack/RSS subscription options. [https://status.column.com, accessed 2026-09-09]
Category 3 · Access Control
5 / 5Read-only credentials
"View Only — Key can view all account activity, but cannot make changes to account information or use the account to initiate transfers." [guides/api-key-security → Permissions]
Scoped credentials
Fine-grained resource and action scoping, not merely role-based. Transfer permissions are set per transfer type: "Each transfer type — ACH credits, ACH debits, ACH returns, wires, deposit checks, issued checks, book transfers, realtime transfers, and stop payments — is set independently, so a key can be granted Create & Edit on ACH credits while remaining View Only on wires." Transfers, entities and bank accounts additionally support per-resource overrides: "Permissions on transfers, entities, and accounts may be overridden on a per-entity and per-account basis." Counterparties, loans, and reports/statements are separately controllable. A further safety layer exists: an API key can never approve a transfer, and per-key Transfer Approvals can hold every eligible transfer from that key for human review. [guides/api-key-security → Custom, Access Levels, Transfer Approvals]
Multiple keys
"One key per workload. Each of your applications should use a separate key. This improves your ability to track and reduce the blast radius of compromised keys." Each key is independently permissioned and bound to one platform and one mode. [guides/api-key-security → Best Practices; → Sandbox and Live Mode]
Rotation and revocation
Self-serve through the dashboard, with a documented procedure: "Rotate periodically. Keys do not expire, so rotation is a procedure you own: issue the replacement, cut traffic over, and confirm the old key is no longer in-use before deleting," and "Revoke compromised keys. If you believe a key has been compromised, revoke it immediately." Key lifecycle is deliberately kept out of the API as a security control - "Keys cannot create, delete or access other keys (or themselves)" - but remains self-serve for a Developer or Admin in the dashboard, requiring no support ticket. [guides/api-key-security → Best Practices, Limitations; guides/roles-and-permissions → Roles]
Test and production isolation
Separate credentials and hard data separation are both documented and were observed. "When you create an API key, you must specify if that key can access sandbox or live mode. Once created, a key's mode may not change," with test_ and live_ prefixes making mode visible at a glance; and "Because of this data isolation, your data is not transferable between sandbox and production." Live-verified: the supplied test_ key operated a complete, fully functional sandbox - "Every route is sandboxed and data persists exactly like in production" - including dedicated simulation endpoints (/simulate/receive-wire, /simulate/receive-ach-credit, /simulate/transfers/ach/settle, and 12 more) for exercising incoming transfers, settlement and ACH return codes. [guides/api-key-security; guides/sandbox-and-testing; live session 2026-09-09]
Category 4 · Docs & AI-Ready
4.4 / 5Complete self-serve reference
A complete, public, example-rich reference. Authentication is documented with a working curl invocation; the API reference at docs.column.com/api is organized by resource across every rail; and the corpus carries worked request and response examples for the core endpoints - the idempotency guide, for instance, shows two full curl calls with their JSON responses demonstrating the deduplicated result. Live testing corroborated the reference: documented request shapes, field names and behaviors matched observed responses on every endpoint exercised, with no reverse-engineering required. [docs.column.com/api; working-with-the-api/authentication, /idempotency, /pagination, /errors; guides/getting-started]
Reliable machine-consumable integration path
A complete, maintained OpenAPI specification suitable for code and tool generation, published in both JSON and YAML. Integrity audit of openapi.json: 141 paths, 180 operations, 224 component schemas; 180 of 180 operations carry an operationId, 180 of 180 carry a summary or description, 180 of 180 define a 2xx response schema, and 0 of 219 distinct $refs are dangling. One strong mechanism is sufficient for yes, and this qualifies comfortably. Noted for completeness, without deduction: Column publishes no official SDKs - its GitHub organization (verified first-party: name "Column", blog https://column.com) contains only 4 public repositories, all forks of third-party Go libraries (zerolog, enumer, go-gin-prometheus, oapi-codegen) - and no MCP server was evidenced. The check awards no extra credit for additional mechanisms. [https://docs.column.com/openapi.json; https://docs.column.com/openapi.yaml; https://github.com/column]
AI-readable documentation
Three complementary first-party resources purpose-built for AI retrieval, and the comprehensiveness requirement is clearly met. llms.txt provides a structured index of the entire documentation tree; llms-full.txt is the complete corpus as a single file (1,242,286 bytes / 21,243 lines) - not an index stub but the full text, which is what this run's own analysis was performed against; and every page is individually retrievable as clean Markdown, documented in Column's own words: "Every page is available as clean Markdown by appending .md to its path under https://docs.column.com/markdown/." Verified by retrieving 11 individual .md pages successfully. Column also publishes a second llms.txt/llms-full.txt pair on its marketing domain. [https://docs.column.com/llms.txt; /llms-full.txt; /markdown/*.md]
Kept current
What is present: https://column.com/changelog/ carries genuine API-level detail rather than marketing summaries, including new endpoints ("Column's Check Deposit API makes it easy for you to deposit checks remotely"; wire drawdowns moving to general availability), new fields ("The wire transfer object now contains the business_function_code"; "We have added a new field to the ACH object called payment_related_info"), and explicit deprecation notices ("The following webhook events have been deprecated and merged to their corresponding events: ach.outgoing_return.initiated"). The exact limitation: publication is irregular and batched rather than continuous - the four most recent entries are dated 30 Sep 2025, 31 Oct 2025, 22 Dec 2025 and 30 Jul 2026, leaving a roughly seven-month gap between December 2025 and July 2026, and the newest entry is about six weeks older than this run date. There is no per-release API changelog, no deprecation-window commitment, and no versioning notes to fall back on (see C2.10). One candidate currency signal was tested and rejected: the sitemap's lastmod dates are not per-page edit timestamps - all 308 URLs share a single identical value (2026-09-08T23:43:23.918Z), i.e. a build timestamp - so they are not evidence that any given page is current.
Category 5 · Access & Cost
15 / 15Self-serve API key
Credential creation is self-serve in the dashboard, with no sales call, support ticket, or key-approval step: "You can create sandbox and production keys in the developer dashboard" (Authentication), and the getting-started guide instructs the operator directly - "you'll need to navigate to the dashboard and copy your api-key." Keys are self-permissioned at creation (Full Access / View Only / Custom), and a Developer or Admin role can manage them without Column's involvement. Live-verified: an operator-created sandbox key authenticated on first use and exercised 180-operation surface areas including reads, writes, lifecycle transitions and webhook management, with no provisioning step required. [working-with-the-api/authentication; guides/getting-started; guides/api-key-security; live session 2026-09-09]
Not commercially gated
No first-party material conditions API access on a premium, top-tier, or upgraded plan, and no meaningful capability was found to be tier-gated. The API is the product: Column's entire documented surface - all 180 operations across accounts, every payment rail, statements, reporting and webhooks - is reached with an ordinary key, and the sandbox is fully featured and free to use ("Every route is sandboxed and data persists exactly like in production"; "Our goal is to allow you to simulate everything that you'll experience in production in our sandbox"). The only documented conditions on reaching production are compliance and identity verification - KYC/KYB on a root entity and, for ACH debit origination specifically, a funded program reserve sized to rolling 60-day debit volume as collateral against returns (guides/going-live). Under this check's own instruction, identity and regulatory verification legally required to conduct the real activity does not count as commercial gating; the program reserve is likewise a risk-collateral requirement tied to originating debits, held in the operator's own named account and returnable, not a fee or a plan tier. One further consideration was weighed and rejected: the corpus documents a per-platform feature-enablement model (error code feature_not_enabled, "Your platform is not enabled for the requested feature. Please contact us"; incoming-transfer holds "available if enabled for your platform"; prenotes requiring feature enablement), and the live run hit feature_not_enabled on the balance-history endpoint. That is not commercial gating on this rubric's terms: nothing in the packet ties any enablement to a price, a plan, or a tier, and the check's partial band asks specifically whether capabilities are tier-gated. Scoring note: the absence of a public pricing page is not a requirement of any check in this rubric and was not treated as a deduction here. [guides/sandbox-and-testing; guides/going-live; guides/api-key-security]
What works
- Every category live-tested: all eight battery steps run, none N-A
- Idempotency proven live, two identical sends produced one transfer rather than two
- Read-only keys, and per-rail scoping so a key can send ACH credits but not wires
- Keys are structurally forbidden from approving transfers, so a human gate cannot be prompted around
- A free, fully featured sandbox with simulation endpoints for incoming transfers, settlement and returns
- 175 documented event types across every rail, with delivery records readable through the API
- A complete OpenAPI 3.0.3 spec: 180 of 180 operations carry an id, a summary and a response schema, with no dangling references
- The whole documentation corpus published for AI retrieval, plus every page as clean Markdown
- A public status page with per-component 90-day uptime and a dated incident history
- Cursor pagination with a published stable-ordering guarantee, verified across a full traversal
What to watch
- No API version you can pin, and no published backward-compatibility or deprecation policy
- Errors carry the wrong HTTP status: a missing bank account returned 400, not 404
- An invalid key returns 401 with an empty body, so there is no structured error at all
- 13 field names carry conflicting types across schemas, including one written as an array that reads back as a string
- The request id on every response is undocumented, so support cannot be relied on to honour it
- No optimistic concurrency: no ETag, no If-Match and no version field on the object
- The changelog publishes in irregular batches, including a seven-month gap
- No official SDKs and no MCP server
- No updated-since filter anywhere, so detecting changed records means using the events feed
- Some capabilities need per-platform enablement, which the live run hit on the balance-history endpoint
The bottom line for a property manager
Column is a real bank, nationally chartered, OCC-regulated and FDIC-insured, holding the accounts itself rather than renting them from a sponsor bank behind the scenes, and its API is one of the most genuinely buildable on this board, with every category live-tested rather than taken on faith. In practice you can open accounts, read balances and transactions, send and receive money on every rail, and cancel, return, reverse or stop-pay anything, all from your own code, with the safety features that matter for automation: read-only and narrowly scoped keys, mandatory human approval on transfers a key initiates, proven protection against accidental double-payments, and a free sandbox you can build against today without talking to anyone. The real limitations are for the people maintaining the integration rather than for the money. Error responses use the wrong HTTP status codes and an invalid key returns a blank response, there is no API version you can pin, and the changelog that would warn you about changes publishes in irregular batches with multi-month gaps. Understand clearly what Column is and is not. It is the bank and the payment rails, not a property management system. It documents FBO and sub-account structures, holds and escrow, and consolidated statements that make trust and operating separation workable, and its property-management page names trust accounts, security deposits, rent, owner distributions and vendor payments. But the API itself has no concept of a lease, a tenant, a unit or an owner statement, and the property-management framing lives largely on the marketing page rather than in the API reference. You would still run a PMS or trust-accounting system on top. A high API score here means Column would be an unusually programmable bank underneath it, not a replacement for it.
Check it yourself.
Both files behind this page, in full.
Column’s full report
The complete markdown report this page is built from, including the evidence packet, the run metadata and every check in full.
Download the Column reportThe grading file
The exact rubric behind every score on this page. Same file, every platform. Run it yourself and compare.
Download the methodologyFound a factual error in your grade?
Tell us and we will fix it. Every mark on this page traces to a specific piece of first-party evidence or a live API call, and the full report is published so you can see exactly what was checked and what it was checked against.
Confirmed factual errors are corrected immediately.
Everything else waits. We do not rescore piecemeal on request, because a board where some vendors have been re-run and others have not is not a fair comparison. Shipped improvements, changed documentation and disagreements about judgement all go into the next full rerun.
Contact us with a factual errorMethodology inspired by SaaStr’s AI Agent API Report Card. Sponsored by Column.