Single Fan View API

The Single Fan View API is designed to enable clients and partners to retrieve data from a subset of FDP modules. As of this writing, the API is read-only, meaning it supports data retrieval from FDP but does not allow writing or modifying data.

GraphQL

The Single Fan View API is built using GraphQL, a powerful query language for APIs, as well as a runtime for executing those queries. GraphQL offers several key advantages that are especially beneficial for this API:

  • Flexible querying: Clients can use any standard GraphQL client to query data, without needing custom request logic.
  • Precise data fetching: Clients specify exactly which fields they need, and the server responds with only that data, reducing payload size and eliminating over-fetching.
  • Client-driven structure: The shape of the response mirrors the structure of the query, giving clients full control over how the data is retrieved and structured.

More information about GraphQL can be found here. Detailed information about the API endpoint for querying FDP modules is available here .

Schema

This section outlines the GraphQL schema for each available FDP module that can be queried. Custom modules are not included in this documentation. If you need to fetch data from a custom module or from a common data module not listed below, please contact our development team for support.

SCV User Schema

type User {
  scvUserId: ID!
  scvUserIdType: String!
  scvClient: String!
  originatingSource: String
  originatingSourceInsight: String
  originatingSourceTstamp: Time
  sourceUpdatedTstamp: Time
  primarySource: String
  deviceId: String
  ssoId: String
  pushId: String
  isPushRevoked: Boolean
  emailAddress: String
  isEmailSuppressed: Boolean
  emailContactId: String
  mobileNumber: String
  title: String
  firstName: String
  lastName: String
  fullName: String
  gender: String
  birthDate: Time
  age: Int
  postcode: String
  postcodeTown: String
  postcodeRegion: String
  postcodeArea: String
  countryCode: String
  countryName: String
  distanceToClub: Float
  jobTitle: String
  companyName: String
  metadata: Map
  createdAt: Time
  updatedAt: Time
}

extend type Query {
  user(scvUserId: ID!): User
}

As shown in the example above, scv_user records can only be queried by id.

The following code snippets illustrate how to query scv_user records by id and what a typical server response looks like:

{
  user(scvUserId:"001beda9967ce420104b2c499265d8ba") {
    scvUserId,
    scvUserIdType,
    fullName,
    postcode,
    postcodeTown,
    postcodeArea,
    postcodeRegion,
    createdAt,
    updatedAt
  }
}
{
  "data": {
    "user": {
      "scvUserId": "001beda9967ce420104b2c499265d8ba",
      "scvUserIdType": "MD5_CLIENT_EMAIL",
      "fullName": "Adrian Clarke",
      "postcode": "80250",
      "postcodeTown": null,
      "postcodeArea": null,
      "postcodeRegion": null,
      "createdAt": "2025-03-21T14:39:43.714066Z",
      "updatedAt": "2025-03-21T14:39:43.714066Z"
    }
  }
}

SCV Retail Schema

type Retail {
    scvUserRetailId:String!
    scvUserId: ID!
    scvClient: String!
    sourceSystemName: String
    sourceSystemUserId: String
    sourceType: String
    branchCode: String
    branchName: String
    departmentName: String
    subDepartmentName: String
    season: String
    productId: String
    productDescription: String
    productCategory: String
    transactionId: String
    transactionDate: Time
    transactionQuantity: Int
    transactionValue: Float
    promoCode: String
    orderId: String
    isRefunded: Boolean
    refundDate: Time
    createdAt: Time
    updatedAt: Time
}

type Retails {
    items: [Retail!]!
    next: String
}

extend type Query {
    retail(scvUserRetailId: ID!): Retail
    retails(scvUserId: String!, size: Int! = 50, sort: [String!] = ["-updatedAt"], cursor: String): Retails!
}

As shown in the example above, scv_user_retail records can be queried by scvUserRetailId or by scvUserId, in which case results are paginated.

The following code snippets illustrate how to query scv_user_retail records by scvUserRetailId and what a typical server response looks like:

{
  retail(scvUserRetailId:"a2aa326d9ace519b7c0ffdabf9b1c7f7") {
    scvUserRetailId
    scvUserId,
		productId,
    promoCode,
    productDescription,
    productCategory,
    transactionId,
    transactionDate,
    transactionValue,
    transactionQuantity,
    createdAt,
    updatedAt
  }
}
{
  "data": {
    "retail": {
      "scvUserRetailId": "a2aa326d9ace519b7c0ffdabf9b1c7f7",
      "scvUserId": "63d911e78be3684af1e80bb73665378d",
      "productId": "4329",
      "promoCode": "5",
      "productDescription": "ex",
      "productCategory": null,
      "transactionId": "48",
      "transactionDate": "2022-10-11T01:40:41+01:00",
      "transactionValue": 667,
      "transactionQuantity": 48,
      "createdAt": "2025-03-17T12:52:38.216598Z",
      "updatedAt": "2025-03-17T12:52:38.216598Z"
    }
  }
}

The following code snippets illustrate how to query scv_user_retail records by scvUserId and what a typical server response looks like:

{
  retails(scvUserId: "63d911e78be3684af1e80bb73665378d", size: 3) {
    items {
      scvUserRetailId
      scvUserId
      productId
      createdAt
      updatedAt
    }
    next
  }
}
{
  "data": {
    "retails": {
      "items": [
        {
          "scvUserRetailId": "ce19ece4822dbe3fa023c241911f29f8",
          "scvUserId": "63d911e78be3684af1e80bb73665378d",
          "productId": "218",
          "createdAt": "2025-03-17T12:52:38.216598Z",
          "updatedAt": "2025-03-17T12:52:38.216598Z"
        },
        {
          "scvUserRetailId": "a2aa326d9ace519b7c0ffdabf9b1c7f7",
          "scvUserId": "63d911e78be3684af1e80bb73665378d",
          "productId": "4329",
          "createdAt": "2025-03-17T12:52:38.216598Z",
          "updatedAt": "2025-03-17T12:52:38.216598Z"
        },
        {
          "scvUserRetailId": "6fde00dc65c664bfd15a4f07e08cf407",
          "scvUserId": "63d911e78be3684af1e80bb73665378d",
          "productId": "218",
          "createdAt": "2025-03-17T12:52:38.216598Z",
          "updatedAt": "2025-03-17T12:52:38.216598Z"
        }
      ],
      "next": "eyJjaWQiOiJJTkNST1dEIiwic3VpZCI6IjYzZDkxMWU3OGJlMzY4NGFmMWU4MGJiNzM2NjUzNzhkIiwic2giOiI2OGMyYzA5MjliNDljZTk1NDE2ZGQ4Mjg2MWIyNDU5NiIsInN2IjpbIjIwMjUtMDMtMTdUMTI6NTI6MzguMjE2NTk4WiIsIjZmZGUwMGRjNjVjNjY0YmZkMTVhNGYwN2UwOGNmNDA3Il19"
    }
  }
}

SCV Ticket Schema

type Ticket {
    scvUserTicketId: String!
    scvUserId: ID!
    sourceSystemName: String
    sourceSystemUserId: String
    sourceType: String
    season: String
    productId: String
    productName: String
    productDescription: String
    productType: String
    productSubType: String
    productStartDate: Time
    productEndDate: Time
    venueName: String
    distanceTravelled: Float
    competitionName: String
    competitionType: String
    homeTeamName: String
    awayTeamName: String
    transactionDate: Time
    transactionDaysBeforeStartDate: Int
    isTransactionCancelled: Boolean
    transactionCancellationDate: Time
    transactionValue: Float
    transactionPriceBand: String
    transactionPriceClass: String
    orderId: String
    orderValue: Float
    paymentMethod: String
    seatNumber: String
    seatRow: String
    blockName: String
    areaName: String
    standName: String
    stadiumName: String
    hasLinkedTicketWallet: Boolean
    isTicketWalletShared: Boolean
    hasAttended: Boolean
    arrivalTime: Time
    createdAt: Time
    updatedAt: Time
}

type Tickets {
    items: [Ticket!]!
    next: String
}

extend type Query {
    ticket(scvUserTicketId: ID!): Ticket
    tickets(scvUserId: String!, size: Int! = 50, sort: [String!] = ["-updatedAt"], cursor: String): Tickets!
}

As shown in the example above, scv_user_ticket records can be queried by scvUserTicketId or by scvUserId, in which case results are paginated.

The following code snippets illustrate how to query scv_user_ticket records by scvUserTicketId and what a typical server response looks like:

{
  ticket(scvUserTicketId: "5e7b885406fa9aa2d71fa24dc1c2cdc8") {
    scvUserTicketId
    scvUserId
    productId
    createdAt
    updatedAt
  }
}
{
  "data": {
    "ticket": {
      "scvUserTicketId": "5e7b885406fa9aa2d71fa24dc1c2cdc8",
      "scvUserId": "001beda9967ce420104b2c499265d8ba",
      "productId": "4",
      "createdAt": "2025-03-17T12:52:41.585747Z",
      "updatedAt": "2025-03-17T12:52:41.585747Z"
    }
  }
}

The following code snippets illustrate how to query scv_user_ticket records by scvUserId and what a typical server response looks like:

{
  tickets(scvUserId: "001beda9967ce420104b2c499265d8ba", size: 3, sort:["-productId", "updatedAt"], cursor: "eyJjaWQiOiJJTkNST1dEIiwic3VpZCI6IjAwMWJlZGE5OTY3Y2U0MjAxMDRiMmM0OTkyNjVkOGJhIiwic2giOiIwZmRjODNmNzU5NTIzNjc4NGIwYTMxNTg5Y2ZlNzFkOSIsInN2IjpbIjQiLCIyMDI1LTAzLTE3VDEyOjUyOjQxLjU4NTc0N1oiLCI3YTRhYzUxNDk4Y2UxNWJjNjVkYzk4NzgyOTdkZmQwNCJdfQ==") {
    items {
      scvUserTicketId
      scvUserId
      productId
      createdAt
      updatedAt
    }
    next
  }
}
{
  "data": {
    "tickets": {
      "items": [
        {
          "scvUserTicketId": "5e7b885406fa9aa2d71fa24dc1c2cdc8",
          "scvUserId": "001beda9967ce420104b2c499265d8ba",
          "productId": "4",
          "createdAt": "2025-03-17T12:52:41.585747Z",
          "updatedAt": "2025-03-17T12:52:41.585747Z"
        },
        {
          "scvUserTicketId": "c3fa65b8200c682af7b48d0003033872",
          "scvUserId": "001beda9967ce420104b2c499265d8ba",
          "productId": "3",
          "createdAt": "2025-03-17T12:52:41.585747Z",
          "updatedAt": "2025-03-17T12:52:41.585747Z"
        },
        {
          "scvUserTicketId": "4657bba432ac7ab8ef448e6ab9be09fa",
          "scvUserId": "001beda9967ce420104b2c499265d8ba",
          "productId": "3",
          "createdAt": "2025-03-17T12:52:41.585747Z",
          "updatedAt": "2025-03-17T12:52:41.585747Z"
        }
      ],
      "next": "eyJjaWQiOiJJTkNST1dEIiwic3VpZCI6IjAwMWJlZGE5OTY3Y2U0MjAxMDRiMmM0OTkyNjVkOGJhIiwic2giOiIwZmRjODNmNzU5NTIzNjc4NGIwYTMxNTg5Y2ZlNzFkOSIsInN2IjpbIjMiLCIyMDI1LTAzLTE3VDEyOjUyOjQxLjU4NTc0N1oiLCI0NjU3YmJhNDMyYWM3YWI4ZWY0NDhlNmFiOWJlMDlmYSJdfQ=="
    }
  }
}

Unlike the previous examples, the code snippet above specifies a page size of 3, uses -productId and updatedAt as sort fields, and includes a cursor to retrieve the next page of results.

SCV Structured Event Schema

type StructuredEvent {
  scvUserStructuredEventId: ID!
  scvUserId: ID!
  scvClient: String!
  sourceSystemName: String
  sourceSystemUserId: String
  sourceType: String
  digitalAppId: String
  usageAt: Time
  category: String
  action: String
  label: String
  property: String
  value: Float
  createdAt: Time
  updatedAt: Time
}

type StructuredEvents {
  items: [StructuredEvent!]!
  next: String
}

extend type Query {
  structuredEvent(scvUserStructuredEventId: ID!): StructuredEvent
  structuredEvents(scvUserId: String!, size: Int! = 50, sort: [String!] = ["-updatedAt"], cursor: String): StructuredEvents!
}

As shown in the example above, scv_user_structured_event records can be queried by scvUserStructuredEventId or by scvUserId, in which case results are paginated.

The following code snippets illustrate how to query scv_user_structured_event records by scvUserStructuredEventId and what a typical server response looks like:

{
  structuredEvent(scvUserStructuredEventId: "7faa7bc3620583bc6a27eb70f6e7103d") {
    scvUserStructuredEventId
    scvUserId
    sourceSystemName
    sourceSystemUserId
    createdAt
    updatedAt
  }
}
{
  "data": {
    "structuredEvent": {
      "scvUserStructuredEventId": "7faa7bc3620583bc6a27eb70f6e7103d",
      "scvUserId": "d76a04e7c89f43c8f8a30affc575641d",
      "sourceSystemName": "SNOWPLOW",
      "sourceSystemUserId": "895",
      "createdAt": "2025-02-27T13:51:15.074019Z",
      "updatedAt": "2025-02-27T13:51:15.074019Z"
    }
  }
}

The following code snippets illustrate how to query scv_user_structured_event records by scvUserId and what a typical server response looks like:

{
  structuredEvents(scvUserId: "d76a04e7c89f43c8f8a30affc575641d", size: 3) {
    items {
      scvUserStructuredEventId
      scvUserId
      sourceSystemName
      sourceSystemUserId
      createdAt
      updatedAt
    }
    next
  }
}
{
  "data": {
    "structuredEvents": {
      "items": [
        {
          "scvUserStructuredEventId": "7faa7bc3620583bc6a27eb70f6e7103d",
          "scvUserId": "d76a04e7c89f43c8f8a30affc575641d",
          "sourceSystemName": "SNOWPLOW",
          "sourceSystemUserId": "895",
          "createdAt": "2025-02-27T13:51:15.074019Z",
          "updatedAt": "2025-02-27T13:51:15.074019Z"
        }
      ],
      "next": null
    }
  }
}

Unlike the previous examples, in the response tab of the code snippet above, the returned cursor (next field) is null, which means there are no other results to be fetched from the API.