String API
Site integrations

Making a request

The integrations endpoints, how to read an action's schema, and a complete Yelp example.

All site integration routes live under one base URL:

https://request.usestring.ai/v1/integrations
RouteKey neededReturns
GET /v1/integrationsNoThe catalog: every site and its actions, with request bands and billing, but no schemas.
GET /v1/integrations/{site}NoOne site's full manifest: each action's input and output JSON Schema, examples and billing.
GET /v1/integrations/manifest.jsonNoThe same, for every site.
POST /v1/integrations/{site}/{action}YesRuns the action on the JSON body.

{site} and {action} are the names in the catalog, such as yelp and business.

Running an action

Send a POST with your key and a JSON body that matches the action's input schema. Each action's section in the catalog lists its input fields, and the manifest carries the same schema.

curl https://request.usestring.ai/v1/integrations/yelp/business \
  -H "Authorization: Bearer $STRING_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "items": ["tonys-pizza-napoletana-san-francisco"] }'
  • The call is synchronous: the response arrives once every input has been read, so set your client's timeout to allow for an action that makes several requests. There is no job to poll.
  • One call can cover many records. An action that reads records by id, such as Yelp business, takes an items array (up to 300 there) and reads the entries concurrently; an entry repeated in items is read once. A paged action, such as Yelp search, takes a pages count instead.
  • The body is validated against the schema before any request is made. Invalid input returns 400 with the failing fields and costs nothing. See Responses & errors.
  • An empty body is treated as {}. The body may be at most 1 MiB; a larger one returns 413.

Worked example: Yelp business

This call asks for two Yelp businesses: one by its alias, and one by a URL that doesn't exist.

curl https://request.usestring.ai/v1/integrations/yelp/business \
  -H "Authorization: Bearer $STRING_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      "tonys-pizza-napoletana-san-francisco",
      "https://www.yelp.com/biz/this-business-does-not-exist-zz9"
    ]
  }'

The response is 200 OK: the first business came back as a row in data, and the second is listed in failures. This is a real response, with the row cut down to a few of its fields:

{
  "envelopeVersion": 1,
  "integration": { "site": "yelp", "action": "business", "version": "1.0.0" },
  "data": [
    {
      "encid": "mSMZJj2pFvttWLpcDmgrEA",
      "alias": "tonys-pizza-napoletana-san-francisco",
      "name": "Tony's Pizza Napoletana",
      "url": "https://www.yelp.com/biz/tonys-pizza-napoletana-san-francisco",
      "addressLine1": "1570 Stockton St",
      "city": "San Francisco",
      "postalCode": "94133",
      "regionCode": "CA",
      "countryCode": "US",
      "latitude": 37.80038939,
      "longitude": -122.40903343,
      "phone": "(415) 835-9888",
      "rating": 4.2,
      "reviewCount": 9018,
      "priceRange": "$$",
      "isCurrentlyOpen": true
    }
  ],
  "failures": [
    {
      "input": "https://www.yelp.com/biz/this-business-does-not-exist-zz9",
      "error": "Yelp does not resolve this business: \"this-business-does-not-exist-zz9\""
    }
  ],
  "warnings": [],
  "requests": [
    {
      "url": "https://graphql-mobile-api.yelp.com/gql/mobile",
      "requestType": "request_standard",
      "requestId": "d2d57cbf-1421-4c28-aeca-1bd6b33ba12f"
    },
    {
      "url": "https://graphql-mobile-api.yelp.com/gql/mobile",
      "requestType": "request_standard",
      "requestId": "e84222ff-571c-4cf8-9640-4c05c6bd9c21"
    },
    {
      "url": "https://graphql-mobile-api.yelp.com/gql/mobile",
      "requestType": "request_standard",
      "requestId": "b9f67a31-d7e0-46e1-8892-d7597c040eee"
    }
  ],
  "billing": { "mode": "passthrough", "calls": 1, "rows": 1 },
  "traceId": "75b7d7a0f6830d88ede9baf9b6cc3934"
}

Reading it:

  • data holds one row per business found. The full row also has categories, review counts by star and by language, opening hours, ordering partners and the newest review; the Yelp page lists every field.
  • failures names each input exactly as you sent it, with the reason it produced no row.
  • requests shows the action made three requests, each billed at the request_standard rate. Those three requests are what this call cost. See Billing.
  • traceId identifies the call. Include it when you contact support.

Responses & errors explains every field and status code.

Reading the schemas

The catalog pages in these docs are generated from the manifest, so you rarely need to read it yourself. Read it when you want to generate a client, validate input before sending it, or notice when an integration changes.

curl https://request.usestring.ai/v1/integrations/yelp

The response, shortened:

{
  "manifestVersion": 2,
  "sites": [
    {
      "name": "yelp",
      "title": "Yelp",
      "description": "Yelp business records, search by term and location, and business reviews, read from Yelp's GraphQL API.",
      "version": "1.0.0",
      "hosts": ["yelp.com"],
      "actions": [
        {
          "name": "business",
          "description": "Read Yelp business records by id, alias or URL: …",
          "input": {
            "type": "object",
            "properties": {
              "items": {
                "type": "array",
                "items": { "type": "string" },
                "description": "Yelp business ids (encid), aliases, or yelp.com/biz/ URLs",
                "minItems": 1,
                "maxItems": 300
              }
            },
            "required": ["items"],
            "additionalProperties": false
          },
          "output": { "type": "array", "items": { "…": "the schema of one row" } },
          "examples": [{ "input": { "items": ["…"] }, "output": [{ "…": "…" }] }],
          "requests": { "min": 1, "max": 2, "per": "item" },
          "billing": { "mode": "perRow", "usd": 0.002 }
        }
      ]
    }
  ]
}
  • input and output are JSON Schemas. output describes the whole data array, so output.items is the schema of one row.
  • hosts are the only domains the site's actions request.
  • requests and billing are explained in Billing. billing is the price the action is listed at, which isn't charged yet.
  • version and manifestVersion are explained in Versioning.

An unknown {site} returns 404.

Polling for changes

The three GET routes send a strong ETag, a Last-Modified time and Cache-Control: public, no-cache. Send the ETag back in If-None-Match, or the time in If-Modified-Since, and an unchanged manifest answers 304 Not Modified with no body. That makes checking for a new version cheap.

curl -i https://request.usestring.ai/v1/integrations \
  -H 'If-None-Match: "6749a615aa22339d4c3aa2bf6c9830cd"'