API Integration

Master the AniList GraphQL API to build powerful features

AniList GraphQL API

AniList uses GraphQL, which means you can request exactly the data you need:

  • Endpoint: https://graphql.anilist.co
  • Method: POST
  • Rate Limit: 90 requests per minute

Setup API Client

Create a GraphQL client in your Flutter app:

lib/core/api/anilist_client.dart

import 'package:http/http.dart' as http;
import 'dart:convert';

class AniListClient {
  static const _endpoint = 'https://graphql.anilist.co';
  final String? _accessToken;

  AniListClient([this._accessToken]);

  Future<Map<String, dynamic>> query({
    required String query,
    Map<String, dynamic>? variables,
  }) async {
    final headers = {
      'Content-Type': 'application/json',
      if (_accessToken != null)
        'Authorization': 'Bearer $_accessToken',
    };

    final body = jsonEncode({
      'query': query,
      if (variables != null) 'variables': variables,
    });

    final response = await http.post(
      Uri.parse(_endpoint),
      headers: headers,
      body: body,
    );

    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      return data['data'];
    } else {
      throw Exception('API Error: ${response.statusCode}');
    }
  }
}

Common Queries

Get Current User

Fetch authenticated user's profile

const query = '''
  query {
    Viewer {
      id
      name
      avatar {
        large
      }
      statistics {
        anime {
          count
          minutesWatched
          episodesWatched
        }
      }
    }
  }
''';

final result = await client.query(query: query);
final user = result['Viewer'];

Search Anime

Search for anime by title

const query = '''
  query ($search: String) {
    Page(page: 1, perPage: 20) {
      media(search: $search, type: ANIME) {
        id
        title {
          romaji
          english
        }
        coverImage {
          large
        }
        format
        status
        episodes
        averageScore
        genres
      }
    }
  }
''';

final result = await client.query(
  query: query,
  variables: {'search': 'Steins Gate'},
);

Mutations

Mutations are used to modify data (requires authentication):

Update List Entry

Update progress, score, or status

const mutation = '''
  mutation (
    $mediaId: Int,
    $status: MediaListStatus,
    $progress: Int,
    $score: Float
  ) {
    SaveMediaListEntry(
      mediaId: $mediaId,
      status: $status,
      progress: $progress,
      score: $score
    ) {
      id
      status
      progress
      score
    }
  }
''';

final result = await client.query(
  query: mutation,
  variables: {
    'mediaId': 21,
    'status': 'COMPLETED',
    'progress': 24,
    'score': 9.5,
  },
);

Rate Limiting

⚠️ Important: AniList API has a rate limit of 90 requests per minute

Implement exponential backoff and caching to avoid hitting limits.

Best Practices

✅ Do:

  • • Cache responses to reduce API calls
  • • Request only the fields you need
  • • Implement retry logic with exponential backoff
  • • Use pagination for large datasets
  • • Handle rate limits gracefully

❌ Don't:

  • • Make unnecessary API calls
  • • Ignore rate limits
  • • Request all fields when only a few are needed
  • • Forget to handle errors
  • • Store access tokens insecurely