{"slug": "how-ai-agents-discover-and-integrate-public-apis", "title": "How AI Agents Discover and Integrate Public APIs", "summary": "Postman's Orbit tool lets developers and AI agents discover and integrate public APIs by describing tasks in plain language, returning callable endpoints with capability evaluations and generating implementation briefs. The author, building a healthcare app, used Orbit's MCP server with Claude to find APIs for calendar checking, appointment writing, and patient emailing, demonstrating the tool's ability to match workflows across multiple services.", "body_md": "# How AI Agents Discover and Integrate Public APIs\n\nThe hardest API to integrate is the one you cannot name.\n\nYou know exactly what the software needs to do: read a calendar, create an event, and send an email when the event is confirmed. What you do not know is which API exposes those capabilities, or whether one API can handle the entire workflow.\n\nThat turns discovery into a brute-force process. Every candidate becomes its own investigation: find the documentation, map the required capabilities to endpoints, inspect the authentication model, test the constraints, and determine what is missing. Most candidates fail only after you have already invested the time to understand them.\n\n## Search by intent, not by name\n\n[Orbit by Postman](https://www.buildwithorbit.ai/welcome) reverses that process. Instead of starting with an API name, you start with the task.\n\nDescribe what you want to build in plain language, and Orbit searches for public API endpoints that match the required capabilities. The result is not another list of documentation pages. Orbit returns callable endpoints with an evaluation of what each one supports, what it does not support, and how well it fits the task.\n\nThat distinction matters. “Calendar API” is a category. “Read events, create an event, and notify the attendee” is an executable workflow. Orbit evaluates APIs against the workflow rather than forcing the developer, or the agent, to infer capabilities from product names and documentation structure.\n\nOnce you select the endpoints, Orbit’s integration step generates a `taskBrief`\n\ncontaining the implementation details an agent needs: authentication, base URLs, request parameters, response shapes, execution order, and the gotchas most likely to break the integration. A single brief can include endpoints from multiple APIs, so the calendar and email portions do not need to come from the same provider. [Orbit’s usage guide](https://www.buildwithorbit.ai/docs/get-started/usage-guide) shows this flow across separate services.\n\nOrbit can be used through its search and integration endpoints or connected to an AI agent through the Model Context Protocol (MCP). Either way, the shift is the same: the agent no longer searches the web, opens five documentation sets, and guesses which APIs fit.\n\nIt describes the outcome. Orbit finds the interfaces that can produce it.\n\n[The launch post](https://blog.postman.com/introducing-orbit-turn-any-task-into-the-right-api-calls/) has the full tour of both tools if you want to dive deeper.\n\n## The feature with no obvious API\n\nMy team is building a healthcare app: patient records, medication, appointments, and scheduling.\n\nBooking already works. A patient picks a slot, we `POST /api/appointments/`\n\n, Postgres gets a record, and the service publishes an `appointment.booked`\n\nevent. `appointment-slots-service`\n\npicks that event up and flips the slot to `booked`\n\n.\n\nNothing else happens. The clinician’s calendar never learns about the appointment, and the patient hears nothing from us after the booking screen. That causes two problems. A clinician who blocks time outside the app will get a patient booked over it, because our slots table can’t see that block. And a patient whose only record of the visit is a page they already closed has nothing reminding them to show up.\n\nSo the feature was clear enough: check the clinician’s calendar before we confirm a slot, write the appointment to that calendar, and email the patient. Three capabilities, and no idea whose API provided them.\n\nThat’s the question Orbit exists to answer, so I stopped guessing and handed the task to it.\n\n## Connecting the MCP server\n\nFirst, I connected to the MCP server using Claude:\n\n```\nclaude mcp add --transport http orbit https://mcp.buildwithorbit.ai/mcp\n```\n\nThen, I restarted my session so the schemas load, and the two tools show up as `search`\n\nand `integrate`\n\n:\n\n```\nsearch    Find and evaluate public API endpoints that match a plain-language\n          goal. Describe what you need in `q`; each result includes `id`,\n          `resourceType`, `name`, `description`, `method`, `url`, and\n          `evaluateGuide`. Review `evaluateGuide` to pick the best fit, then\n          pass each chosen result's `id` and `resourceType` (as `type`) to\n          `integrate`. No authentication required.\n\nintegrate Get integration details for public endpoints from `search` results.\n          Provide a `task` describing what you want to accomplish and up to 10\n          `resources`. Returns a task brief covering authentication, base URLs,\n          request steps, parameters, expected responses, dependencies between\n          steps, and other important considerations.\n```\n\nRead the `search`\n\ndescription again, because it’s doing something clever. It tells the model to review `evaluateGuide`\n\nbefore choosing, and it names the exact field to carry into `integrate`\n\n. The chaining rule lives in the tool description rather than in my prompt, so the agent runs the two-step workflow without me explaining it. That’s the difference between an MCP server that wraps an API and one that encodes how the API is meant to be used.\n\n## Searching for an API I couldn’t name\n\nI opened the GitHub repo locally, started Claude Code in it, and described the feature the way I’d describe it to a colleague:\n\n```\n> The appointments service publishes appointment.booked but nothing reaches the\n  clinician's real calendar. Find me an API that can check whether a clinician\n  is free before we confirm a slot.\n```\n\n*The same session, unedited. Two Orbit [search] calls, and the endpoint IDs coming back in the response.*\n\nNote what the agent did to my sentence. I described a product problem, and it sent calendar vocabulary. That translation is the thing that makes or breaks a search here.\n\nWhat came back was the Nylas Calendar API, and two endpoints that answer subtly different versions of my question:\n\n| Endpoint | Question it answers | Scope constraint |\n|---|---|---|\n`POST /v3/grants/{grant_id}/calendars/free-busy` |\n“Is this clinician busy between T1 and T2?” Raw busy blocks, with no titles, locations, or descriptions. | Grant-scoped, and every email address has to be on the same provider: all Google or all Microsoft. |\n`POST /v3/calendars/availability` |\n“Which N-minute slots are open across these people?” | Application-scoped, and it only returns availability for addresses already connected to your Nylas app. |\n\nI hadn’t gone looking for [Nylas](https://developer.nylas.com/docs/v3/getting-started/); the search surfaced it, which is the whole point. Both paths are scoped to a [grant](https://developer.nylas.com/docs/v3/getting-started/), which is one connected mailbox and calendar that a clinic authorizes once through OAuth. A Google clinic and a Microsoft clinic are the same code path with a different grant.\n\n## Integrating the API\n\nSearch hands you endpoints. `integrate`\n\nturns them into something an agent can write code against.\n\nThe call takes two things: the task, in the same plain language I used for search, and the endpoints I picked out of the results.\n\n```\n● orbit - integrate (MCP)\n  task: \"When a patient books an appointment slot in a healthcare app, read the\n         clinician's calendar to check for conflicts, create a calendar event\n         for the visit, and send the patient a confirmation email\"\n  resources:\n    - id: urn:orbit:endpoint:v1:1JfnSC668Gw0xjByXOjgh0EA8G3qVd4A…:nylas:return-all-events\n      type: endpoint\n    - id: urn:orbit:endpoint:v1:1JfnSC668Gw0xcUnlXP6gVtFBZ6Qk8nL…:nylas:create-an-event\n      type: endpoint\n    - id: urn:orbit:endpoint:v1:1JfnSC668Gw0yW6A9NI5lL7NJrnkapSj…:nylas:send-a-message\n      type: endpoint\n```\n\nWhat comes back is one `taskBrief`\n\nunder five headings: `FIT`\n\n, `AUTH`\n\n, `BASE URL`\n\n, `STEPS`\n\n, and `GOTCHAS`\n\n. The middle two are one line each, and both are things I’d otherwise go find in a docs site:\n\n```\nAUTH\n  Bearer authentication for all steps. Send the Nylas API key as\n  `Authorization: Bearer <bearerToken>`; the collection references\n  {{bearerToken}}, but does not provide its value.\n\nBASE URL\n  https://api.us.nylas.com for all steps.\n```\n\n`STEPS`\n\nis the bulk of the brief. Each step gets its method and path, every parameter with the place it goes, and an example value. It ends with the success and error response shapes and a `Threading`\n\nline saying what the step takes from the one before it:\n\n```\n1. GET /v3/grants/{grant_id}/events\n   Params:\n     calendar_id: string — e.g. `cal_123`; query parameter, required by the\n       supplied URL.\n     grant_id: string — e.g. `grant_123`; path variable.\n     limit: integer — `50`; query parameter, up to 200.\n     Optional conflict filters: `page_token`, `start` and `end`,\n       `show_cancelled`, `busy`, `title`, `description`, `location`, …\n   Returns:\n     200 OK; `data[]` containing events and a `request_id`. Errors include 400\n     with `request_id` and `error` (`type`, `message`, `provider_error`), or\n     401 with the same error shape.\n   Threading:\n     None\n```\n\n## The brief told me what would break\n\nThe two sections I didn’t expect to be useful were `FIT`\n\nand `GOTCHAS`\n\n. Here is the `FIT`\n\nsection of the brief, verbatim as Orbit returned it:\n\n```\nFIT\n  Fully. The supplied requests cover calendar conflict checking, event\n  creation, and confirmation-email sending. They are related by the\n  appointment task but do not consume a value returned by another request,\n  so each request is described in order without fabricated response threading.\n```\n\nRead that `FIT`\n\nsection closely. It says the three requests don’t consume each other’s return values, so it declines to invent threading between them. A generated guide that refuses to fabricate a dependency chain beats one that produces plausible glue code, because plausible glue code is what I debug later.\n\nFurther down the same brief, the event-creation step handed me the body shape directly:\n\n```\n2. POST /v3/grants/{grant_id}/events\n   Params:\n     grant_id: string — e.g. 'grant_123' (path)\n     calendar_id: string — e.g. 'cal_123' or 'primary' (query)\n     JSON body:\n       title: string — 'Patient appointment'\n       busy: boolean — true\n       visibility: string — 'private'\n       participants: array of objects\n       when: object — {\"start_time\":1690862400,\"end_time\":1690866000,\n                       \"start_timezone\":\"America/New_York\",\n                       \"end_timezone\":\"America/New_York\"}\n       reminders: object — {\"use_default\":false,\"overrides\":[...]}\n```\n\nAnd then the `GOTCHAS`\n\nsection, again verbatim, which is the part I’d normally learn from a failed request:\n\n```\nGOTCHAS\n  - Use epoch seconds and the specified timezone fields in the event's\n    when object.\n  - The event and email calls are separate mutations; do not retry either\n    blindly. Use a unique Idempotency-Key for safe email retries.\n  - Some event fields may be null, including busy, calendar_id, when,\n    reminders.use_default, and reminders.overrides.\n  - Check all relevant event pages and compare the requested appointment\n    interval with returned event timing before creating the event; use\n    page_token for subsequent pages.\n```\n\nThree steps, the auth and base URL, plus the gotchas above: that’s the entire integration spec, and all of it arrived before I’d opened a browser tab.\n\nSo why not skip all of this and tell the agent “integrate Nylas v3 for me”? I’d get code. It would look right. The difference is where the details come from: my brief was generated against the [Nylas v3 collection on the Postman API Network](https://www.postman.com/trynylas/nylas-api/collection/fn1ujmb/v3-nylas-email-and-calendar-apis), the same indexed source the search matched. A model working without that is working from whatever it absorbed about Nylas during training, and the four things that broke my integration are exactly the things recall gets wrong:\n\n**Formats.**`when.start_time`\n\nis epoch seconds. Nothing about a JSON booking payload suggests that, and ISO-8601 is the confident guess.**Nullability.**`busy`\n\ncan come back null and means`true`\n\n. Guess`false`\n\nand you double-book a clinician.**Retry semantics.** The`Idempotency-Key`\n\nheader on the send call is the difference between a retry and a patient getting two confirmation emails.**Dependencies.**`Threading: None`\n\non all three steps is a claim, not a blank, and`FIT`\n\nsays it again in prose. The brief looked for values passed between the calls, found none, and said so. Ask a model to wire up three endpoints and it will thread them instead, because plausible beats absent and chained calls are what integration code looks like.\n\nI still had to write the consumer. What I didn’t have to do was learn any of this from a 400.\n\n## Writing the feature from the brief\n\nThis is the part the whole search was for. The brief named the three calls, their bodies, and their failure modes, so what was left was deciding where in our app to put them. I didn’t have to compare providers or dig through documentation. I had to wire three known requests into a service that already existed.\n\nThe platform already publishes domain events over Kafka, so I didn’t touch the appointments service at all. `appointment-slots-service`\n\nshows the pattern, subscribing to the same topic to flip slot state.\n\nCalendar sync is another consumer on that topic. Keeping it out of the booking request path means a Nylas outage delays a confirmation email instead of failing a patient’s booking, which is the tradeoff I want.\n\n*The three numbered calls run in the order the task brief listed them.*\n\nEverything is in [healthcare-calendar-sync](https://github.com/healthcare-org-app/healthcare-calendar-sync) if you want to read it end to end, including the [test suite](https://github.com/healthcare-org-app/healthcare-calendar-sync/blob/main/tests/test_consumers.py) that asserts the brief’s gotchas against a faked Postgres, Kafka, and Nylas.\n\nOne stop before you point any of this at a real mailbox. Nylas publishes its [v3 collection on the Postman API Network](https://www.postman.com/trynylas/nylas-api/collection/fn1ujmb/v3-nylas-email-and-calendar-apis), the same collection Orbit indexed to answer my search. Fork it into your workspace and every request from the task brief is ready to send. That’s the cheapest place to check the epoch-second format and the idempotency header, before a patient is on the other end of them.\n\n## What I’d tell the next person\n\n**Name the mechanism, not the feature.**“Create a calendar event for a booked appointment” could pull back a school calendar system or an integration platform, because “calendar event” and “appointment” match anything carrying those nouns. “Find available free busy time slots before booking a meeting” returned the API I needed three times over. So look at what the endpoints*are*before anything else: results from unrelated domains mean your query was too generic, not that the API doesn’t exist. And don’t read`meta.total`\n\nas a match count. It reports the size of the page you asked for.**Read**`GOTCHAS`\n\n**before you write the client.** Epoch seconds, nullable`busy`\n\n, and the`Idempotency-Key`\n\nheader were all sitting in the brief. Each one is a bug I’d otherwise have shipped and then heard about from a support ticket.**The most useful line is the one about what an endpoint won’t do.**“Not supported” in`evaluateGuide`\n\nis the highest-value part of the search response. Nylas has separate endpoints for creating a draft and sending it, and the guide says so in the search result instead of making me find out from a 400.\n\n## The week I didn’t spend\n\nThe integration itself is unremarkable: one Kafka consumer, three HTTP calls, and a thin client around them. What Orbit compressed was everything before that, where I knew the shape of the feature but not the name of the API.\n\n`search`\n\npointed me at an API that had been built for my task. `integrate`\n\ngave me the request bodies, the epoch-second format, the nullable field that would have caused double-bookings, and the idempotency header that keeps patients from getting duplicate mail. That last set is the part I value, because those are the failures that surface in production rather than in review.\n\nTry it on something you’re stuck on. One command:\n\n```\nclaude mcp add --transport http orbit https://mcp.buildwithorbit.ai/mcp\n```\n\nThen take a feature you’ve been putting off because you don’t know what to integrate with, and describe it in one sentence:\n\n```\n> We need to <the capability you're missing>. Search Orbit for an API that\n  does it, show me the evaluateGuide for the top results, then get the\n  integration brief for whichever ones you'd pick.\n```\n\nRead the `evaluateGuide`\n\nlines before you open a docs site, and read `GOTCHAS`\n\nbefore you write the client. Those two habits are what turned a week of provider comparison into an afternoon of writing a consumer. Then tell me whether the brief caught something you’d have shipped, because I’d like to know if my three were typical.\n\n## Resources\n\n[Introducing Orbit: Turn Any Task Into the Right API Calls](https://blog.postman.com/introducing-orbit-turn-any-task-into-the-right-api-calls/), the launch post[Orbit documentation](https://www.buildwithorbit.ai/welcome)and the[usage guide](https://www.buildwithorbit.ai/docs/get-started/usage-guide)[Orbit search endpoint reference](https://www.buildwithorbit.ai/api-reference/search-public-endpoints)and[integrate endpoint reference](https://www.buildwithorbit.ai/api-reference/integrate-public-endpoints)[Orbit OpenAPI specification](https://www.buildwithorbit.ai/openapi.json)[Nylas v3 collection on the Postman API Network](https://www.postman.com/trynylas/nylas-api/collection/fn1ujmb/v3-nylas-email-and-calendar-apis)[healthcare-calendar-sync](https://github.com/healthcare-org-app/healthcare-calendar-sync), the complete service from this post[myhealthcare.dev API reference](https://myhealthcare.docs.buildwithfern.com/api-reference)and[appointments service repo](https://github.com/healthcare-org-app/healthcare-appointments)", "url": "https://wpnews.pro/news/how-ai-agents-discover-and-integrate-public-apis", "canonical_source": "https://blog.postman.com/how-ai-agents-discover-and-integrate-public-apis/", "published_at": "2026-09-02 16:00:00+00:00", "updated_at": "2026-09-02 16:25:30.353801+00:00", "lang": "en", "topics": ["ai-tools", "ai-agents", "developer-tools"], "entities": ["Postman", "Orbit", "Claude", "Model Context Protocol (MCP)"], "alternates": {"html": "https://wpnews.pro/news/how-ai-agents-discover-and-integrate-public-apis", "markdown": "https://wpnews.pro/news/how-ai-agents-discover-and-integrate-public-apis.md", "text": "https://wpnews.pro/news/how-ai-agents-discover-and-integrate-public-apis.txt", "jsonld": "https://wpnews.pro/news/how-ai-agents-discover-and-integrate-public-apis.jsonld"}}